জটিল টাইপ পোস্ট করতে কীভাবে System.Net.HttpClient ব্যবহার করবেন?


102

আমার একটি কাস্টম জটিল ধরণ রয়েছে যা আমি ওয়েব এপিআই ব্যবহার করে কাজ করতে চাই।

public class Widget
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

এবং এখানে আমার ওয়েব এপিআই নিয়ন্ত্রণকারী পদ্ধতি। আমি এই বিষয়টির মতো পোস্ট করতে চাই:

public class TestController : ApiController
{
    // POST /api/test
    public HttpResponseMessage<Widget> Post(Widget widget)
    {
        widget.ID = 1; // hardcoded for now. TODO: Save to db and return newly created ID

        var response = new HttpResponseMessage<Widget>(widget, HttpStatusCode.Created);
        response.Headers.Location = new Uri(Request.RequestUri, "/api/test/" + widget.ID.ToString());
        return response;
    }
}

এবং এখন আমি System.Net.HttpClientপদ্ধতিতে কল করতে ব্যবহার করতে চাই । তবে PostAsyncপদ্ধতিতে কোন ধরণের অবজেক্টটি পাস করতে হবে এবং কীভাবে এটি নির্মাণ করা যায় সে সম্পর্কে আমি নিশ্চিত নই । এখানে কিছু নমুনা ক্লায়েন্ট কোড।

var client = new HttpClient();
HttpContent content = new StringContent("???"); // how do I construct the Widget to post?
client.PostAsync("http://localhost:44268/api/test", content).ContinueWith(
    (postTask) =>
    {
        postTask.Result.EnsureSuccessStatusCode();
    });

HttpContentওয়েব এপিআই এটি বুঝতে পারে এমনভাবে কীভাবে আমি বস্তুটি তৈরি করব?


আপনি কি নিজের অবজেক্টের এক্সএমএল সিরিয়ালাইজড সংস্করণটি পরিষেবা শেষ বিন্দুতে জমা দেওয়ার চেষ্টা করেছেন?
জোশুয়া ড্রাক

উত্তর:


132

জেনেরিকটি সরানোHttpRequestMessage<T> হয়েছে । এই :

new HttpRequestMessage<Widget>(widget)

আর কাজ করবে না

পরিবর্তে, এই পোস্ট থেকে , এএসপি.এনইটি টিম এই কার্যকারিতাটি সমর্থন করার জন্য কয়েকটি নতুন কল অন্তর্ভুক্ত করেছে :

HttpClient.PostAsJsonAsync<T>(T value) sends application/json
HttpClient.PostAsXmlAsync<T>(T value) sends application/xml

সুতরাং, নতুন কোড ( ডানস্টন থেকে ) হয়ে যায়:

Widget widget = new Widget()
widget.Name = "test"
widget.Price = 1;

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:44268");
client.PostAsJsonAsync("api/test", widget)
    .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode() );

1
হ্যাঁ, তবে যদি আপনার উইজেট শ্রেণিতে অ্যাক্সেস না থাকে?
পরিচিতিমেট

13
নতুন HttpClient.PostAsXXXAsync<T>( T value ) methods are great, but what about one for application/x-www-form-urlencoded format? Is there a simple / short way for that or do we still need to create elaborate কীভ্যালিউপায়ার তালিকা?
জানস

1
@ জ্যানস ফ্লুরল। এইচটিটিপি এর মাধ্যমে একটি সহজ / স্বল্প পথ সরবরাহ করে PostUrlEncodedAsync
টড মেনিয়ার

16
নোট করুন যে আপনি System.Net.Http. বিন্যাস করতে সক্ষম হতে ফর্ম্যাট করতে PostAsJsonAsyncবাPostAsXmlAsync
পিট

6
PostAsJsonAcync ব্যবহার করতে, নুগেট প্যাকেজটি মাইক্রোসফ্ট.এএসপনেট.ওয়েবএপিআই.ক্লিয়েন্ট যুক্ত করুন !!
ডেনিস

99

SendAsyncপরিবর্তে আপনার পদ্ধতিটি ব্যবহার করা উচিত , এটি একটি জেনেরিক পদ্ধতি, সেবার ইনপুটটিকে সিরিয়ালাইজ করে

Widget widget = new Widget()
widget.Name = "test"
widget.Price = 1;

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:44268/api/test");
client.SendAsync(new HttpRequestMessage<Widget>(widget))
    .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode() );

আপনি কংক্রিট বর্গ তৈরি করতে না চান তাহলে, আপনি এটি দিয়ে করতে পারেন FormUrlEncodedContentবর্গ

var client = new HttpClient();

// This is the postdata
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("Name", "test"));
postData.Add(new KeyValuePair<string, string>("Price ", "100"));

HttpContent content = new FormUrlEncodedContent(postData); 

client.PostAsync("http://localhost:44268/api/test", content).ContinueWith(
    (postTask) =>
    {
        postTask.Result.EnsureSuccessStatusCode();
    });

দ্রষ্টব্য: আপনাকে আপনার আইডিটি একটি ননাল ইন্টি ( int?) করতে হবে


1
এটি একটি বহিরাগত প্রকল্প থেকে কল করা হবে, যেখানে আমার কাছে উইজেট অবজেক্ট সম্বলিত সমাবেশের কোনও রেফারেন্স থাকবে না। আমি একটি বেনামে টাইপ করা অবজেক্ট তৈরি করার চেষ্টা করেছি যাতে সঠিক বৈশিষ্ট্য রয়েছে, এই পদ্ধতিটি ব্যবহার করে এটি সিরিয়ালকরণ করা হচ্ছে এবং সেভাবে পাস করা হয়েছে, তবে আমি একটি 500 অভ্যন্তরীণ সার্ভার ত্রুটি পেয়েছি। এটি ওয়েব এপিআই নিয়ন্ত্রণকারী পদ্ধতিটিকে কখনও আঘাত করে না।
indot_brad

ওহ - তারপরে আপনাকে ওয়েবপিপি পরিষেবাতে এক্সএমএল, বা জসন পোস্ট করতে হবে, এবং এটি এটির ডিজিয়ালাইজেশন করবে - এটি একই কাজ করে সেন্ডসায়েন্স সার্ভিসের জন্য বিষয়টিকে সিরিয়ালাইজ করছে
ডানস্টন

1
সবেমাত্র একটি আপডেট করেছি - আমার কোডটি টেস্টেটে রয়েছে তবে কিছু সহজ কোড সহ, তবে আমার কাজ করা উচিত
ডানস্টন

8
আমি "নন-জেনেরিক টাইপ 'সিস্টেম.নেট। এইচটিটিপি.এইচটিপিআরকোয়েস্টমেসেজ' ধরণের আর্গুমেন্টের সাথে ব্যবহার করা যায় না"। এটি কি এখনও বৈধ?
ব্যবহারকারী 10479

5
হ্যাঁ প্রথম সমাধানটি আর কাজ করে না: aspnetwebstack.codeplex.com/discussion/350492
জিওভান্নি বি

74

মনে রাখবেন যে আপনি যদি কোনও পোর্টেবল ক্লাস লাইব্রেরি ব্যবহার করেন তবে এইচটিপিপি্লিয়েন্টের পোস্টএএসজসনসাইক পদ্ধতি থাকবে না । একটি পোর্টেবল ক্লাস লাইব্রেরি ব্যবহার করে JSON হিসাবে কোনও সামগ্রী পোস্ট করতে, আপনাকে এটি করতে হবে:

HttpClient client = new HttpClient();
HttpContent contentPost = new StringContent(argsAsJson, Encoding.UTF8, 
"application/json");

await client.PostAsync(new Uri(wsUrl), contentPost).ContinueWith(
(postTask) => postTask.Result.EnsureSuccessStatusCode());

যখন আরগ্যাসএএসজেসন একটি সিরিয়ালযুক্ত অবজেক্ট থেকে আসে এবং এই বস্তুর একটি সম্পত্তি থাকে ie সামগ্রী = "ডোমেন \ ব্যবহারকারী", তারপরে \ দু'বার এনকোড হবে। একবার আরগ্যাসএএসজেসনে সিরিয়ালীকৃত হয়ে ওঠার পরে এবং দ্বিতীয়বার যখন পোস্টএন্সিঙ্কটি সামগ্রী পোস্ট করে। কীভাবে ডাবল এনকোডিং এড়ানো যায়?
ক্রিজিসটফ মরকিনেক

3
দুর্দান্ত @ ফাবিয়ানো! এটি সত্যিই কৌতুক করেছে। এই জাতীয় প্রকল্পে এই দুটি অতিরিক্ত যুক্তি প্রয়োজনীয় necessary
পিটার ক্লিন

@ পিটারক্লেইন খুব ভাল! ওয়েবে মাইক্রোসফ্টের ডকুমেন্টেশনের মধ্যে আমি এই তথ্যটি খুঁজে পাইনি, সুতরাং এটি অন্যদের একই সমস্যা সহকারে সহায়তা করতে পারে। আমার প্রকল্পটি সহজভাবে এই কৌশলটি ছাড়াই ডেটা প্রেরণ করে না।
ফাবিয়ানো

1
নোট আপনার কাছে অনুরোধ মধ্যে "অ্যাপ্লিকেশন / JSON" যোগ আছে পারে যে হেডার গ্রহণ করুন যে, প্রতি stackoverflow.com/a/40375351/3063273
ম্যাট টমাস

4

আপনি যদি অন্যান্য উত্তরে উল্লিখিত প্রকারের সুবিধাদির পদ্ধতিগুলি দেখতে চান তবে বহনযোগ্যতার প্রয়োজন হয় (বা আপনি নাও করেন) তবে আপনি ফ্লারল [প্রকাশ: আমি লেখক] যাচাই করতে চাইতে পারেন । এটি ( HttpClientসরুভাবে ) মোড়ানো এবং জসন.এনইটি এবং কিছু বেকড ইন টেস্টিং সহায়ক সহ কিছু সাবলীল চিনি এবং অন্যান্য গুডি যুক্ত করে ।

জেএসএন হিসাবে পোস্ট করুন:

var resp = await "http://localhost:44268/api/test".PostJsonAsync(widget);

বা URL- এনকোডযুক্ত:

var resp = await "http://localhost:44268/api/test".PostUrlEncodedAsync(widget);

উপরের দুটি HttpResponseMessageউদাহরণই একটি ফেরত দেয় , তবে ফ্লুরলে অন্য জিনিসগুলি ফিরিয়ে দেওয়ার জন্য এক্সটেনশন পদ্ধতিগুলি অন্তর্ভুক্ত করা হয় যদি আপনি কেবল তাড়া করতে চান:

T poco = await url.PostJsonAsync(data).ReceiveJson<T>();
dynamic d = await url.PostUrlEncodedAsync(data).ReceiveJson();
string s = await url.PostUrlEncodedAsync(data).ReceiveString();

ফুরল নুগেটে উপলভ্য:

PM> Install-Package Flurl.Http

1

প্রচুর বিকল্প তদন্ত করার পরে, আমি এপিআই ২.০ সংস্করণে উপযোগী অন্য পদ্ধতির মুখোমুখি হয়েছি।

(ভিবি.এনইটি আমার প্রিয়, সুন্দর ...)

Public Async Function APIPut_Response(ID as Integer, MyWidget as Widget) as Task(Of HttpResponseMessage)
    Dim DesiredContent as HttpContent = New StringContent(JsonConvert.SerializeObject(MyWidget))
    Return Await APIClient.PutAsync(String.Format("api/widget/{0}", ID), DesiredContent)
End Function

শুভকামনা! আমার জন্য এটি কাজ করেছে (শেষ পর্যন্ত!)।

শুভেচ্ছা, পিটার


1
@ ফ্যাবিওর উপরোক্ত পরামর্শগুলির সাথে এটি জিনিসগুলি ঘটায়।
পিটার ক্লেইন

2
VB.NET কোনও পছন্দ নয় :)
অলস কোডার

1

আমি মনে করি আপনি এটি করতে পারেন:

var client = new HttpClient();
HttpContent content = new Widget();
client.PostAsync<Widget>("http://localhost:44268/api/test", content, new FormUrlEncodedMediaTypeFormatter())
    .ContinueWith((postTask) => { postTask.Result.EnsureSuccessStatusCode(); });

1

আমার মতো কেউ যদি উপরের সমস্ত বিষয়গুলি সম্পর্কে সত্যই বুঝতে না পারে তবে আমি একটি সহজ উদাহরণ দিচ্ছি যা আমার পক্ষে কাজ করছে। আপনার যদি একটি ওয়েব এপিআই থাকে যা ইউআরএল " http://somesite.com/verifyAddress " হয়, এটি একটি পোস্ট পদ্ধতি এবং এটি আপনাকে একটি ঠিকানা বস্তুটি পাস করার প্রয়োজন। আপনি আপনার কোড এ এই এপি কল করতে চান। এখানে আপনি কি করতে পারেন।

    public Address verifyAddress(Address address)
    {
        this.client = new HttpClient();
        client.BaseAddress = new Uri("http://somesite.com/");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        var urlParm = URL + "verifyAddress";
        response = client.PostAsJsonAsync(urlParm,address).Result;
        var dataObjects = response.IsSuccessStatusCode ? response.Content.ReadAsAsync<Address>().Result : null;
        return dataObjects;
    }

0

আমি এখানে অন্য উত্তরগুলির উপর ভিত্তি করে কোডটি দিয়েছিলাম wound এটি এমন কোনও এইচটিপিপোস্টের জন্য যা জটিল ধরণের সাথে গ্রহণ করে এবং প্রতিক্রিয়া জানায়:

Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(
                       strMyHttpPostURL,
                       new MyComplexObject { Param1 = param1, Param2 = param2}).ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
                    //debug:
                    //String s = response.Result.Content.ReadAsStringAsync().Result;
                    MyOtherComplexType moct = (MyOtherComplexType)JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result, typeof(MyOtherComplexType));

-1

এইভাবে একটি পরিষেবা কল করুন:

public async void SaveActivationCode(ActivationCodes objAC)
{
    var client = new HttpClient();
    client.BaseAddress = new Uri(baseAddress);
    HttpResponseMessage response = await client.PutAsJsonAsync(serviceAddress + "/SaveActivationCode" + "?apiKey=445-65-1216", objAC);
} 

এবং এর মতো পরিষেবা পদ্ধতি:

public HttpResponseMessage PutSaveActivationCode(ActivationCodes objAC)
{
}

PutAsJsonAsync নেটওয়ার্কের মাধ্যমে সিরিয়ালাইজেশন এবং deserialization এর যত্ন নেয়


এটি একটি HTTP পুট বার্তা প্রেরণ করবে, অনুরোধ হিসাবে কোনও পোষ্ট নয়। অন্যরা যেমন বলেছে PostAsJsonAsyncযে প্রয়োজনীয় তথ্য পাঠাবে, জেএসএনে একটি পোস্ট হিসাবে।
ঝাফ - বেন ডুগুইড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.