WebAPI मल्टीपल पुट / पोस्ट पैरामीटर


154

मैं एक WebAPI नियंत्रक पर कई मापदंडों को पोस्ट करने की कोशिश कर रहा हूं। एक परम URL से है, और दूसरा शरीर से है। यहाँ url है: /offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

यहाँ मेरा नियंत्रक कोड है:

public HttpResponseMessage Put(Guid offerId, OfferPriceParameters offerPriceParameters)
{
    //What!?
    var ser = new DataContractJsonSerializer(typeof(OfferPriceParameters));
    HttpContext.Current.Request.InputStream.Position = 0;
    var what = ser.ReadObject(HttpContext.Current.Request.InputStream);

    return new HttpResponseMessage(HttpStatusCode.Created);
}

JSON में शरीर की सामग्री है:

{
    "Associations":
    {
        "list": [
        {
            "FromEntityId":"276774bb-9bd9-4bbd-a7e7-6ed3d69f196f",
            "ToEntityId":"ed0d2616-f707-446b-9e40-b77b94fb7d2b",
            "Types":
            {
                "list":[
                {
                    "BillingCommitment":5,
                    "BillingCycle":5,
                    "Prices":
                    {
                        "list":[
                        {
                            "CurrencyId":"274d24c9-7d0b-40ea-a936-e800d74ead53",
                            "RecurringFee":4,
                            "SetupFee":5
                        }]
                    }
                }]
            }
        }]
    }
}

कोई भी विचार क्यों डिफ़ॉल्ट बाइंडिंग offerPriceParametersमेरे नियंत्रक के तर्क के लिए बाध्य करने में सक्षम नहीं है ? यह हमेशा अशक्त करने के लिए सेट है। लेकिन मैं का उपयोग करके शरीर से डेटा को पुनर्प्राप्त करने में सक्षम हूं DataContractJsonSerializer

मैं भी FromBodyतर्क की विशेषता का उपयोग करने की कोशिश करता हूं , लेकिन यह भी काम नहीं करता है।

जवाबों:


78
[HttpPost]
public string MyMethod([FromBody]JObject data)
{
    Customer customer = data["customerData"].ToObject<Customer>();
    Product product = data["productData"].ToObject<Product>();
    Employee employee = data["employeeData"].ToObject<Employee>();
    //... other class....
}

संदर्भ का उपयोग कर

using Newtonsoft.Json.Linq;

JQuery के अजाक्स के लिए अनुरोध का उपयोग करें

var customer = {
    "Name": "jhon",
    "Id": 1,
};
var product = {
    "Name": "table",
    "CategoryId": 5,
    "Count": 100
};
var employee = {
    "Name": "Fatih",
    "Id": 4,
};

var myData = {};
myData.customerData = customer;
myData.productData = product;
myData.employeeData = employee;

$.ajax({
    type: 'POST',
    async: true,
    dataType: "json",
    url: "Your Url",
    data: myData,
    success: function (data) {
        console.log("Response Data ↓");
        console.log(data);
    },
    error: function (err) {
        console.log(err);
    }
});

3
महान समाधान। यदि यह पहले से ही दूसरों के लिए स्पष्ट नहीं है, तो आप भी उपयोग कर सकते हैं। .ToObject <int> (), .ToObject <दशमलव> (), .ToString (), आदि। यदि आप सरल में गुजर रहे हैं, तो आपके ajax कॉल से कई पैरामीटर।
गुप्तवृत्त

धन्यवाद, मैंने अपना स्वयं का एपीआई बनाकर और पोस्टमैन के माध्यम से परीक्षण करके आपके समाधान की कोशिश की है और यह ठीक काम कर रहा है; लेकिन मैंने var test = {"Name": "test"} जैसे चौथे पैरामीटर को जोड़ा है और इसे myData ऑब्जेक्ट में जोड़ा है और इसे सफलतापूर्वक भेजा गया था; वैसे भी इससे बचने और केवल मूल वस्तुओं को प्रतिबंधित करने के लिए क्या है?
Mlle116

@ H.Al No, Newtonsoft.Json में किसी भी तरह का जोंस डेटा हो सकता है जो लाइब्रेरी को अनुवाद के बारे में पता हो। आप डेटा भेजने से नहीं रोक सकते। यह आने वाले डेटा का उपयोग करने के लिए आप पर निर्भर करता है
Fatih GDRDAL

63

Natively WebAPI कई POST मापदंडों के बंधन का समर्थन नहीं करता है। जैसा कि कॉलिन बताते हैं कि मेरे ब्लॉग पोस्ट में उनके द्वारा उल्लिखित कई सीमाएँ हैं ।

कस्टम पैरामीटर बाइंडर बनाकर वर्कअराउंड है। ऐसा करने के लिए कोड बदसूरत और जटिल है, लेकिन मैंने अपने ब्लॉग पर एक विस्तृत विवरण के साथ कोड पोस्ट किया है, यहां एक परियोजना में प्लग किए जाने के लिए तैयार है:

ASP.NET वेब एपीआई में कई सरल POST मान पास करना


1
इसका सारा श्रेय आपको जाता है :) मैं अभी-अभी WebAPI पर अपनी श्रंखला को पढ़ते हुए अपना कार्यान्वयन शुरू कर रहा हूं जब यह प्रश्न पॉप अप हुआ।
कॉलिन यंग

धन्यवाद! बहुत मददगार।
नॉर्मैंड बेडर्ड

2
2019 तक यह अभी चल रहा है।
अधिकतम

@ जॉन - एक आधार संस्करण है जिससे यह कार्यक्षमता समर्थित है? आज कोई सफलता नहीं मिल रही है।
नील मॉस

26

यदि विशेषता रूटिंग का उपयोग किया जा रहा है, तो आप [FromUri] और [FromBody] विशेषताओं का उपयोग कर सकते हैं।

उदाहरण:

[HttpPost()]
[Route("api/products/{id:int}")]
public HttpResponseMessage AddProduct([FromUri()] int id,  [FromBody()] Product product)
{
  // Add product
}

1
मैंने ठीक उसी विधि का उपयोग किया है। मुझे कार्रवाई करने के लिए दो मॉडल पास करने की आवश्यकता है। मैंने क्वेरी स्ट्रिंग और अन्य बॉडी से कम गुणों के साथ एक पास किया है। इसके अलावा आपको स्पष्ट रूप से [FromBody] attribyte
सर्गेई जी।

1
मैं यह काम नहीं कर सकता, क्या आपके पास और अधिक पूर्ण उदाहरण है?
एक

मुझे नहीं लगता कि यह POST विधि के माध्यम से डेटा भेजने का सही तरीका है, लेकिन मुझे एक और समाधान नहीं दिखाई देता है यदि आपको पोस्ट के माध्यम से 2 मॉडल भेजने हैं।
एलेक्जेंड्रा

यह उत्तर है जाम!
लियोनार्डो वाइल्ड

1
मैं Aspnetcore का उपयोग कर रहा हूं और आपको [FromRoute]इसके बजाय का उपयोग करना होगा[FromUri]
DanielV

19

हमने Json ऑब्जेक्ट को HttpPost विधि से पास किया, और इसे डायनेमिक ऑब्जेक्ट में पार्स किया। यह बढ़िया काम करता है। यह नमूना कोड है:

WebAPI:

[HttpPost]
public string DoJson2(dynamic data)
{
   //whole:
   var c = JsonConvert.DeserializeObject<YourObjectTypeHere>(data.ToString()); 

   //or 
   var c1 = JsonConvert.DeserializeObject< ComplexObject1 >(data.c1.ToString());

   var c2 = JsonConvert.DeserializeObject< ComplexObject2 >(data.c2.ToString());

   string appName = data.AppName;
   int appInstanceID = data.AppInstanceID;
   string processGUID = data.ProcessGUID;
   int userID = data.UserID;
   string userName = data.UserName;
   var performer = JsonConvert.DeserializeObject< NextActivityPerformers >(data.NextActivityPerformers.ToString());

   ...
}

जटिल वस्तु प्रकार वस्तु, सरणी और शब्दकोश हो सकता है।

ajaxPost:
...
Content-Type: application/json,
data: {"AppName":"SamplePrice",
       "AppInstanceID":"100",
       "ProcessGUID":"072af8c3-482a-4b1c‌​-890b-685ce2fcc75d",
       "UserID":"20",
       "UserName":"Jack",
       "NextActivityPerformers":{
           "39‌​c71004-d822-4c15-9ff2-94ca1068d745":[{
                 "UserID":10,
                 "UserName":"Smith"
           }]
       }}
...

1
हम पोस्ट करने के लिए एक जोंस ऑब्जेक्ट के रूप में स्वरूपित कई मापदंडों को रख सकते हैं, और हम इसे बाद में सर्वर साइड में कई ऑब्जेक्ट्स के लिए पार्स करेंगे। यह सोचने का एक और तरीका हो सकता है।
बेस लाई

@EkoosticMartin, यह ठीक काम करता है, आपको उपयोग करके गतिशील प्रकार को पार्स करने की आवश्यकता है: JsonConvert.DeserializeObject <YourObjectTypeHere> (data.ToString ()); एक जटिल डेटा सामग्री नमूना यहां है, इसमें सरणी और शब्दकोश वस्तु शामिल है। { "APPNAME": "SamplePrice", "AppInstanceID": "100", "ProcessGUID": "072af8c3-482a-4b1c-890b-685ce2fcc75d", "UserID": "20", "उपयोगकर्ता नाम": "जैक" " NextActivityPerformers ": {" 39c71004-d822-4c15-9ff2-94ca1068d745 ": [{" UserID ": 10," UserName ":" Smith ""}}}}
Bes Ley

1
ठीक है यकीन है, तो बस एक स्ट्रिंग स्ट्रिंग का उपयोग करें, वहाँ कोई अंतर नहीं है।
एकोस्तिकमार्टिन

सिंगल नॉट का अर्थ है सरल, json string को कई अलग-अलग प्रकार की वस्तुओं के साथ जोड़ा जा सकता है। यह प्रमुख बिंदु है, और प्रश्नों को हल करने का एक और तरीका है।
बेस ले

1
उत्कृष्ट समाधान! धन्यवाद :)
कार्ल आर

10

एक साधारण पैरामीटर वर्ग का उपयोग किसी पोस्ट में कई मापदंडों को पारित करने के लिए किया जा सकता है:

public class AddCustomerArgs
{
    public string First { get; set; }
    public string Last { get; set; }
}

[HttpPost]
public IHttpActionResult AddCustomer(AddCustomerArgs args)
{
    //use args...
    return Ok();
}

कोई भी मौका आपको पता है कि नमूना POST अनुरोध को कैसे देखना चाहिए?
नादिया सोलोयेवा

@NadiaSolovyeva, यह एक क्वेरी स्ट्रिंग से अधिक है, क्योंकि पोस्ट की गई जानकारी शरीर में है, क्वेरी स्ट्रिंग नहीं। मैं टेस्ट क्वेश्चन बनाने के लिए पोस्टमैन का उपयोग करना पसंद करता हूं, और फिर आप वास्तव में यह देख सकते हैं कि यह कैसा दिखता है।
ग्रेग गम

कोई बात नहीं, मैंने पहले ही पाया है कि यह कैसे करना है। पोस्ट हेडर: कंटेंट-टाइप: एप्लीकेशन / जसन; POST बॉडी: {"फर्स्ट": "1", "लास्ट": "1000"}
नादिया सोलोयेवा

9

आप https://Pithub.com/keith5000/MultiPostParameterBinding से MultiPostParameterBinding वर्ग का उपयोग करके कई POST मापदंडों की अनुमति दे सकते हैं

इसके प्रयेाग के लिए:

1) स्रोत फ़ोल्डर में कोड डाउनलोड करें और इसे अपने वेब एपीआई परियोजना या समाधान में किसी अन्य परियोजना में जोड़ें।

2) कई POST मापदंडों का समर्थन करने की जरूरत है कि कार्रवाई के तरीकों पर विशेषता [MultiPostParameters] का उपयोग करें ।

[MultiPostParameters]
public string DoSomething(CustomType param1, CustomType param2, string param3) { ... }

3) GlobalConfiguration.Configure (WebApiConfig.Register) पर कॉल करने से पहले कहीं भी इस लाइन को Global.asax.cs में Application_Start पद्धति में जोड़ें :

GlobalConfiguration.Configuration.ParameterBindingRules.Insert(0, MultiPostParameterBinding.CreateBindingForMarkedParameters);

4) क्या आपके ग्राहक किसी वस्तु के गुणों के रूप में पैरामीटर पास करते हैं। DoSomething(param1, param2, param3)विधि के लिए एक उदाहरण JSON ऑब्जेक्ट है:

{ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }

उदाहरण JQuery:

$.ajax({
    data: JSON.stringify({ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }),
    url: '/MyService/DoSomething',
    contentType: "application/json", method: "POST", processData: false
})
.success(function (result) { ... });

अधिक जानकारी के लिए लिंक पर जाएँ ।

अस्वीकरण: मैं सीधे जुड़े हुए संसाधन के साथ जुड़ा हुआ हूं।


7

अच्छा सवाल और टिप्पणी - यहाँ उत्तरों से बहुत कुछ सीखा :)

एक अतिरिक्त उदाहरण के रूप में, ध्यान दें कि आप शरीर और मार्गों को भी मिला सकते हैं

[RoutePrefix("api/test")]
public class MyProtectedController 
{
    [Authorize]
    [Route("id/{id}")]
    public IEnumerable<object> Post(String id, [FromBody] JObject data)
    {
        /*
          id                                      = "123"
          data.GetValue("username").ToString()    = "user1"
          data.GetValue("password").ToString()    = "pass1"
         */
    }
}

इस तरह कॉलिंग:

POST /api/test/id/123 HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer x.y.z
Cache-Control: no-cache

username=user1&password=pass1


enter code here

मैं 2 जटिल प्रकार के पैरामीटर भेजना चाहूंगा। जैसे कि [HttpPost] सार्वजनिक स्ट्रिंग UploadFile (UploadMediaFile MediaFile, byte [] डेटा) यह कैसे करना है।
बैसार काया

2

इस मामले के लिए आपका रूटटेम्पलेट कैसा दिखता है?

आपने यह url पोस्ट किया:

/offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

यह काम करने के लिए मैं आपके लिए इस तरह से एक रूटिंग की उम्मीद करूंगा WebApiConfig:

routeTemplate: {controller}/{offerId}/prices/

अन्य धारणाएँ हैं: - आपका नियंत्रक कहा जाता है OffersController। - जिस JSON ऑब्जेक्ट को आप रिक्वेस्ट बॉडी में पास कर रहे हैं, वह टाइप का है OfferPriceParameters(किसी व्युत्पन्न प्रकार का नहीं) - आपके पास कंट्रोलर पर कोई अन्य तरीका नहीं है जो इस एक के साथ हस्तक्षेप कर सके (यदि आप करते हैं, तो उन्हें टिप्पणी करके देखें और देखें हो जाता)

और जैसा कि फ़िलिप ने उल्लेख किया है कि यह आपके प्रश्नों में मदद करेगा यदि आप कुछ उत्तरों को '0% की स्वीकार दर' के रूप में स्वीकार करना शुरू कर सकते हैं, तो हो सकता है कि लोग यह सोचें कि वे अपना समय बर्बाद कर रहे हैं


मेरा मार्ग "ऑफ़र / {ऑफ़रआईडीडी / मूल्य" है। मेरे नियंत्रक में यह एकमात्र तरीका है।
नॉर्मैंड बेडार्ड

2

यदि आप मॉडलबाइंडिंग रास्ते पर नहीं जाना चाहते हैं, तो आप ऐसा करने के लिए डीटीओ का उपयोग कर सकते हैं। उदाहरण के लिए, DataLayer में एक POST क्रिया बनाएँ जो एक जटिल प्रकार स्वीकार करती है और BusinessLayer से डेटा भेजती है। आप इसे UI-> API कॉल के मामले में कर सकते हैं।

यहाँ नमूना डीटीओ हैं। एक छात्र को एक शिक्षक असाइन करें और छात्र को कई कागजात / विषय सौंपे।

public class StudentCurriculumDTO
 {
     public StudentTeacherMapping StudentTeacherMapping { get; set; }
     public List<Paper> Paper { get; set; }
 }    
public class StudentTeacherMapping
 {
     public Guid StudentID { get; set; }
     public Guid TeacherId { get; set; }
 }

public class Paper
 {
     public Guid PaperID { get; set; }
     public string Status { get; set; }
 }

तो DataLayer में कार्रवाई के रूप में बनाया जा सकता है:

[HttpPost]
[ActionName("MyActionName")]
public async Task<IHttpActionResult> InternalName(StudentCurriculumDTO studentData)
  {
     //Do whatever.... insert the data if nothing else!
  }

BusinessLayer से इसे कॉल करने के लिए:

using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", dataof_StudentCurriculumDTO)
  {
     //Do whatever.... get response if nothing else!
  }

अब यह तब भी काम करेगा जब मैं एक बार में एक से अधिक छात्रों का डेटा भेजना चाहता हूं। MyActionनीचे की तरह संशोधित करें। [FromBody] लिखने की कोई आवश्यकता नहीं है, WebAPI2 डिफ़ॉल्ट रूप से जटिल प्रकार [FromBody] लेता है।

public async Task<IHttpActionResult> InternalName(List<StudentCurriculumDTO> studentData)

और फिर इसे कॉल करते समय, List<StudentCurriculumDTO>डेटा पास करें।

using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", List<dataof_StudentCurriculumDTO>)

0

अनुरोध मापदंडों की तरह

यहाँ छवि विवरण दर्ज करें

वेब एप कोड जैसा होना चाहिए

public class OrderItemDetailsViewModel
{
    public Order order { get; set; }
    public ItemDetails[] itemDetails { get; set; }
}

public IHttpActionResult Post(OrderItemDetailsViewModel orderInfo)
{
    Order ord = orderInfo.order;
    var ordDetails = orderInfo.itemDetails;
    return Ok();
}

0

आप सूत्र के रूप में स्ट्रिंग प्राप्त कर सकते हैं:

    protected NameValueCollection GetFormData()
    {
        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        Request.Content.ReadAsMultipartAsync(provider);

        return provider.FormData;
    }

    [HttpPost]
    public void test() 
    {
        var formData = GetFormData();
        var userId = formData["userId"];

        // todo json stuff
    }

https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.