ऑब्जेक्ट के रूप में वेब एपीआई विधि में json POST डेटा कैसे पास करें?


304

ASP.NET MVC4 वेब एपीआई एप्लिकेशन ग्राहक को बचाने के लिए पोस्ट विधि को परिभाषित करता है। ग्राहक POST अनुरोध निकाय में json प्रारूप में पारित किया जाता है। पोस्ट विधि में ग्राहक पैरामीटर में गुणों के लिए शून्य मान शामिल हैं।

इसे कैसे ठीक करें ताकि पोस्ट किया गया डेटा ग्राहक ऑब्जेक्ट के रूप में पारित हो जाए?

यदि संभव हो तो सामग्री-प्रकार: एप्लिकेशन / x-www-form-urlencoded का उपयोग किया जाना चाहिए क्योंकि मुझे नहीं पता कि इसे कैसे जावास्क्रिप्ट विधि में बदलना है जो पदों को बनाता है।

नियंत्रक:

public class CustomersController : ApiController {

  public object Post([FromBody] Customer customer)
        {
            return Request.CreateResponse(HttpStatusCode.OK,
            new
            {
                customer = customer
            });
        }
    }
}

public class Customer
    {
        public string company_name { get; set; }
        public string contact_name { get; set; }
     }

निवेदन:

POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

{"contact_name":"sdfsd","company_name":"ssssd"}

जवाबों:


525

EDIT : 31/10/2017

समान कोड / अप्रोच Asp.Net Core 2.0 के लिए भी काम करेगा । मुख्य अंतर यह है कि, asp.net कोर में, वेब एपीआई नियंत्रक और Mvc नियंत्रक दोनों को एकल नियंत्रक मॉडल में एक साथ विलय कर दिया जाता है। अपनी वापसी प्रकार हो सकता है तो IActionResultयह के कार्यान्वयन में से एक या (उदाहरण: OkObjectResult)


उपयोग

contentType:"application/json"

JSON.stringifyजब आप इसे भेजते हैं तो आपको इसे JSON स्ट्रिंग में बदलने के लिए विधि का उपयोग करने की आवश्यकता होती है,

और मॉडल बाइंडर आपके क्लास ऑब्जेक्ट पर जोंस डेटा को बांध देगा।

नीचे दिया गया कोड ठीक काम करेगा (परीक्षण किया गया)

$(function () {
    var customer = {contact_name :"Scott",company_name:"HP"};
    $.ajax({
        type: "POST",
        data :JSON.stringify(customer),
        url: "api/Customer",
        contentType: "application/json"
    });
});

परिणाम

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

contentTypeसंपत्ति सर्वर को बताती है कि हम JSON प्रारूप में डेटा भेज रहे हैं। चूंकि हमने JSON डेटा संरचना भेजी थी, इसलिए मॉडल बाइंडिंग ठीक से होगी।

यदि आप ajax अनुरोध के हेडर का निरीक्षण करते हैं, तो आप देख सकते हैं कि Content-Typeमान के रूप में सेट किया गया है application/json

यदि आप सामग्री प्रकार स्पष्ट रूप से निर्दिष्ट नहीं करते हैं, तो यह डिफ़ॉल्ट सामग्री प्रकार का उपयोग करेगा जो है application/x-www-form-urlencoded;


टिप्पणियों में उठाए गए अन्य संभावित मुद्दों को संबोधित करने के लिए नवंबर 2015 पर संपादित करें

एक जटिल वस्तु पोस्ट करना

मान लीजिए कि आपके पास आपके वेब एपी एक्शन मेथड पैरामीटर जैसा एक जटिल दृश्य मॉडल वर्ग है

public class CreateUserViewModel
{
   public int Id {set;get;}
   public string Name {set;get;}  
   public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
  public int Id {set;get;}
  public string Code {set;get;}
}

और आपका वेब एपीआई अंत बिंदु जैसा है

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewModel Save([FromBody] CreateUserViewModel m)
    {
        // I am just returning the posted model as it is. 
        // You may do other stuff and return different response.
        // Ex : missileService.LaunchMissile(m);
        return m;
    }
}

इस लेखन के समय, ASP.NET MVC 6 नवीनतम स्थिर संस्करण है और MVC6 में, वेब एपीआई नियंत्रक और MVC नियंत्रक दोनों Microsoft.AspNet.Mvc.Controllerआधार वर्ग से विरासत में मिले हैं ।

क्लाइंट की ओर से विधि को डेटा भेजने के लिए, नीचे दिए गए कोड को ठीक काम करना चाहिए

//Build an object which matches the structure of our view model class
var model = {
    Name: "Shyju",
    Id: 123,
    Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};

$.ajax({
    type: "POST",
    data: JSON.stringify(model),
    url: "../product/save",
    contentType: "application/json"
}).done(function(res) {       
    console.log('res', res);
    // Do something with the result :)
});

मॉडल बंधन कुछ गुणों के लिए काम करता है, लेकिन सभी नहीं! क्यों ?

यदि आप [FromBody]विशेषता के साथ वेब एपीआई विधि पैरामीटर को नहीं सजाते हैं

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}

और ContentType संपत्ति मान निर्दिष्ट किए बिना मॉडल (कच्ची जावास्क्रिप्ट ऑब्जेक्ट, JSON प्रारूप में नहीं) भेजें

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});

मॉडल बाइंडिंग मॉडल पर फ्लैट गुणों के लिए काम करेगा, न कि उन गुणों पर जहाँ प्रकार जटिल है / अन्य प्रकार। हमारे मामले में, Idऔर Nameगुण पैरामीटर के लिए ठीक से बाध्य होंगे m, लेकिन Tagsसंपत्ति एक खाली सूची होगी।

यदि आप लघु संस्करण का उपयोग कर रहे हैं तो वही समस्या होगी, $.postजो अनुरोध भेजते समय डिफ़ॉल्ट सामग्री-प्रकार का उपयोग करेगा।

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});

4
निश्चित नहीं कि मैंने क्या किया, लेकिन मैं आज सुबह वापस आया और उसी नाव में वापस आया। नियंत्रक में ऑब्जेक्ट अशक्त है। यहाँ हम
ग्रेसन

1
सुनिश्चित करें कि जब आप फ़िडलर का उपयोग कर रहे हों, तब सामग्री प्रकार "सामग्री-प्रकार: अनुप्रयोग / json" लिखा जाए। चीयर्स!
20

1
आपने बस मुझे काम का दिन हल कर दिया !!! इस छोटे से कार्य "JSON.stringify (डेटा)" ने इसे बनाया!
गिल एलन

1
ध्यान रखें कि यदि आप ऐसा करते हैं (सामग्री-प्रकार हेडर बदलें) और आप एक कोर अनुरोध कर रहे हैं, तो jQuery आपके POST से पहले प्रीफ़्लाइट विकल्प अनुरोध जोड़ना शुरू कर देगा जिसे सर्वर को संभालना होगा।
आर्बिटर

1
जटिल प्रकारों के साथ समस्या के कारण मुझे लगता है कि यह सिर्फ 'स्पेसिफिकेशन': 'एप्लीकेशन / जॅक्सन' के लिए एक आदत है; और js js ऑब्जेक्ट को कड़ा करता है और फिर [FromBody] विशेषता का उपयोग करने की कोई आवश्यकता नहीं है।
बॉर्नटूकोड

69

Webapi में POST के साथ काम करना मुश्किल हो सकता है! पहले से ही सही उत्तर में जोड़ना चाहते हैं ..

विशेष रूप से POST पर ध्यान केंद्रित किया जाएगा क्योंकि GET के साथ काम करना तुच्छ है। मुझे नहीं लगता कि कई लोग वेब के साथ जीईटी के साथ एक मुद्दे को हल करने के लिए चारों ओर खोज रहे हैं। वैसे भी ..

यदि आपका प्रश्न है - MVC वेब एप में, कैसे करें - सामान्य HTTP क्रियाओं के अलावा कस्टम एक्शन विधि नामों का उपयोग करें? - कई पोस्ट करें? - कई सरल प्रकार पोस्ट करें? - jQuery के माध्यम से जटिल प्रकार पोस्ट करें?

तब निम्नलिखित समाधान मदद कर सकते हैं:

सबसे पहले, वेब एपीआई में कस्टम एक्शन मेथड्स का उपयोग करने के लिए , एक वेब एपीआई मार्ग जोड़ें:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}");
}

और फिर आप कार्रवाई के तरीके बना सकते हैं:

[HttpPost]
public string TestMethod([FromBody]string value)
{
    return "Hello from http post web api controller: " + value;
}

अब, अपने ब्राउज़र कंसोल से निम्न jQuery को फायर करें

$.ajax({
    type: 'POST',
    url: 'http://localhost:33649/api/TestApi/TestMethod',
    data: {'':'hello'},
    contentType: 'application/x-www-form-urlencoded',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

दूसरा, कई पोस्ट करने के लिए , यह सरल है, कई एक्शन तरीके बनाएं और [HttpPost] अट्रिब के साथ सजाएं। कस्टम नाम निर्दिष्ट करने के लिए [ActionName ("MyAction")] का प्रयोग करें, नीचे चौथे बिंदु में jQuery आएगा

तीसरा, सबसे पहले, एक ही कार्रवाई में कई SIMPLE प्रकार पोस्ट करना संभव नहीं है। इसके अलावा, यहां तक ​​कि एक भी सरल प्रकार पोस्ट करने के लिए एक विशेष प्रारूप है (क्वेरी स्ट्रिंग या रीस्ट स्टाइल में पैरामीटर पास करने के अलावा)। यह वह बिंदु था जिसने मुझे रेस्ट क्लाइंट्स (जैसे कि फिडलर और क्रोम के उन्नत आरईएसटी क्लाइंट एक्सटेंशन) के साथ अपना सिर पीटना था और अंततः जब लगभग 5 घंटे तक वेब पर शिकार किया, तो निम्न URL मददगार साबित हुआ। लिंक के लिए प्रासंगिक सामग्री को उद्धृत करेगा जो मृत हो सकता है!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"na@Turbo.Tina"}

पुनश्च: अजीब वाक्यविन्यास पर ध्यान नहीं दिया ?

http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

वैसे भी, हम उस कहानी पर आते हैं। आगे बढ़ते रहना:

चौथा, jQuery के माध्यम से जटिल प्रकारों को पोस्ट करना , tocourse, $ .ajax () तुरंत भूमिका में आना है:

बता दें कि एक्शन मेथड में एक पर्सन ऑब्जेक्ट होता है, जिसमें एक आईडी और एक नाम होता है। तो, जावास्क्रिप्ट से:

var person = { PersonId:1, Name:"James" }
$.ajax({
    type: 'POST',
    url: 'http://mydomain/api/TestApi/TestMethod',
    data: JSON.stringify(person),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

और कार्रवाई की तरह दिखेगा:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}

उपरोक्त सभी, मेरे लिए काम किया !! चीयर्स!


2
मैं हर कुछ महीनों में इस समस्या से टकराता हूं, ज्यादातर समय मैं अंततः इसे हल करता हूं, लेकिन इस बार मैंने हार मान ली है। ऊपर दिए गए सुझावों में से कोई भी मेरे लिए इसे हल नहीं करता है, इसलिए मैंने इसे एक दृष्टिकोण के रूप में बिन करने का फैसला किया। यदि यह सही है, तो परेशान क्यों है? वैसे भी यह केवल एक सुविधा है - बस सामग्री को एक स्ट्रिंग के रूप में लें और इसे बदलने के लिए newtonsoft का उपयोग करें। किया हुआ। इसे "आसान" तरीके से हल करने के लिए लगभग एक घंटे के प्रयास के बाद इसे "कठिन" तरीके से हल करने में शायद 30 सेकंड लगे। मैं दृष्टिकोण के बारे में जंगली नहीं हूं, लेकिन क्या इसके साथ कोई मौलिक समस्या है?
काइनेटिक

PS: WebApi2 में, अब हम रूट डेकोरेटर्स का उपयोग कर सकते हैं। इसलिए यह मुद्दा मुख्य रूप से संबोधित है। asp.net/web-api/overview/web-api-rout-and-actions/…
वैभव

2
एक अवलोकन जोड़ना चाहेंगे। कभी-कभी, WebAPI की ओर से मॉडल-बाइंडिंग के विफल (अशक्त) होने का कारण, जब एक जटिल प्रकार (उदा: DTO) गुजरता है, तो यह है कि मॉडल में एक या अधिक गुण असंगत (या पार्स करने में विफल) होंगे। उदाहरण के लिए। एक गाइड संपत्ति को एक अमान्य GUID सौंपा जा रहा है। इस स्थिति में, सभी ऑब्जेक्ट गुणों के लिए डिफ़ॉल्ट / खाली मानों का उपयोग करके पुनः प्रयास करें।
वैभव

10

मैं सिर्फ इसके साथ खेल रहा हूं और इसके बजाय एक अजीब परिणाम की खोज की है। कहो कि आपके पास C # में अपनी श्रेणी के सार्वजनिक गुण हैं:

public class Customer
{
    public string contact_name;
    public string company_name;
}

तो आपको ShSON द्वारा सुझाए गए JSON.stringify ट्रिक को करना चाहिए और इसे इस तरह से कॉल करना चाहिए:

var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});

हालाँकि, यदि आप गेटर्स को परिभाषित करते हैं और इस तरह अपनी कक्षा में बसते हैं:

public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}

तो आप इसे और अधिक बस कह सकते हैं:

$.ajax({
    type: "POST",
    data :customer,
    url: "api/Customer"
});

यह HTTP हेडर का उपयोग करता है:

Content-Type:application/x-www-form-urlencoded

मुझे यकीन नहीं है कि यहां क्या हो रहा है लेकिन यह फ्रेम में बग (सुविधा?) जैसा दिखता है। संभवतः अलग-अलग बाध्यकारी तरीके अलग-अलग "एडेप्टर" कह रहे हैं, और जबकि एप्लिकेशन / जसन के लिए एडॉप्टर सार्वजनिक गुणों के साथ काम करता है, फॉर्म एनकोडेड डेटा के लिए कोई नहीं करता है।

मेरे पास कोई विचार नहीं है जिसे हालांकि सबसे अच्छा अभ्यास माना जाएगा।


6
प्रॉपर्टीज बनाम फील्ड्स क्यों इसके अलग हैं। गुण सर्वोत्तम अभ्यास हैं। जिसे आप पहले उदाहरण में गुण कहते हैं, वास्तव में, फ़ील्ड हैं। जब आप उन पर गेट / सेट लगाते हैं, तो उनके पास एक ऑटो बैकिंग फ़ील्ड होता है जो उन्हें गुण बनाता है।
पकाओगोमेज़

यह बहुत सच है, और विषम है। केवल फ़ील्ड वाले सामान्य वर्ग पोस्ट बनाने के लिए बाध्य नहीं होंगे, लेकिन गुण होंगे। BTW: फिर भी समझा नहीं है कि यह मामला क्यों है ...? मैं केवल अंदाज़ा लगा सकता हूँ कि आंतरिक तर्क केवल JSON डेटा को फ़ील्ड्स से बाँधेंगे, और पोस्ट डेटा को गुणों के रूप में बनाएंगे, और बस यही है ...?
जेम्स विल्किंस

1
यह मामला है क्योंकि कोड केवल गुणों के लिए दिखता है। चूंकि सार्वजनिक क्षेत्रों का उपयोग करना सबसे अच्छा अभ्यास नहीं है, इसलिए एमएस टीम ने सर्वोत्तम अभ्यास परिदृश्यों की अनुमति नहीं देने का फैसला किया , बहुत अच्छा कारण आईएमएचओ।
एरिक फिलिप्स

1

JSON फॉर्मेट में स्ट्रिंग प्राप्त करने के लिए JSON.stringify () का उपयोग करें , सुनिश्चित करें कि AJAX कॉल करते समय आप नीचे बताए गए तरीके से पास करें:

  • सामग्री प्रकार: 'आवेदन / json'

नीचे asp.net वेब एपि को ajax पोस्ट कॉल करने के लिए jquery कोड दिया गया है:

var product =
    JSON.stringify({
        productGroup: "Fablet",
        productId: 1,
        productName: "Lumia 1525 64 GB",
        sellingPrice: 700
    });

$.ajax({
    URL: 'http://localhost/api/Products',
    type: 'POST',
    contentType: 'application/json',
    data: product,
    success: function (data, status, xhr) {
        alert('Success!');
    },
    error: function (xhr, status, error) {
        alert('Update Error occurred - ' + error);
    }
});


2
dataType की आवश्यकता नहीं है।
एरिक फिलिप्स

0

सुनिश्चित करें कि आपकी WebAPI सेवा JSON से मेल खाने वाली संरचना के साथ जोरदार टाइप की गई वस्तु की अपेक्षा कर रही है। और सुनिश्चित करें कि आप उस JSON को कड़े करते हैं जिसे आप POST कर रहे हैं।

यहाँ मेरा जावास्क्रिप्ट (AngluarJS का उपयोग करके) है:

$scope.updateUserActivity = function (_objuserActivity) {
        $http
        ({
            method: 'post',
            url: 'your url here',
            headers: { 'Content-Type': 'application/json'},
            data: JSON.stringify(_objuserActivity)
        })
        .then(function (response)
        {
            alert("success");
        })
        .catch(function (response)
        {
            alert("failure");
        })
        .finally(function ()
        {
        });

और यहाँ मेरा WebAPI नियंत्रक है:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}

0

Xml -Web API 2 के बजाय json फॉर्मेट में डेटा वापस करने के लिए निम्नलिखित कोड: -

निम्नलिखित लाइन को Global.asax फ़ाइल में रखें

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

0
@model MVCClient.Models.ProductDetails

@{
    ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">

    $(document).ready(function () {
        $("#Save").click(function () {
            var ProductDetails = new Object();
            ProductDetails.ProductName =  $("#txt_productName").val();
            ProductDetails.ProductDetail = $("#txt_desc").val();
            ProductDetails.Price= $("#txt_price").val();
            $.ajax({
                url: "http://localhost:24481/api/Product/addProduct",
                type: "Post",
                dataType:'JSON',
                data:ProductDetails, 

                success: function (data) {
                    alert('Updated Successfully');
                    //window.location.href = "../Index";
                },
                error: function (msg) { alert(msg); }
            });
        });
    });
    </script>
<h2>ProductDetails</h2>

<form id="form1" method="post">
    <fieldset>
        <legend>ProductDetails</legend>


        <div class="editor-label">
            @Html.LabelFor(model => model.ProductName)
        </div>
        <div class="editor-field">

            <input id="txt_productName" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductDetail)
        </div>
        <div class="editor-field">

            <input id="txt_desc" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductDetail)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">

            <input id="txt_price" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.Price)
        </div>



        <p>
            <input id="Save" type="button" value="Create" />
        </p>
    </fieldset>

</form>
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>

</form>



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

0

Microsoft ने ऐसा करने का एक अच्छा उदाहरण दिया:

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

पहले अनुरोध को मान्य करें

if (ModelState.IsValid)

और क्रमबद्ध डेटा का उपयोग करने से।

Content = new StringContent(update.Status)

यहाँ 'स्टेटस' जटिल प्रकार का एक क्षेत्र है। Serializing .NET द्वारा किया जाता है, इसके बारे में चिंता करने की कोई आवश्यकता नहीं है।


0

1) अपने ग्राहक पक्ष में आप नीचे की तरह स्ट्रिंग में http.post अनुरोध भेज सकते हैं

var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}

2) फिर अपने वेब एपीआई नियंत्रक में आप इसे deserialize कर सकते हैं

public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
    {
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}

3) आपका ApiReivedivedListOfObjects वर्ग नीचे जैसा होना चाहिए

public class ApiReceivedListOfObjects<T>
    {
        public List<T> element { get; set; }

    }

4) सुनिश्चित करें कि आपका क्रमबद्ध स्ट्रिंग (IndexInfo यहां) JsonConvert.DeserializeObject कमांड से पहले चरण 2 में संरचना से नीचे की तरह हो जाता है

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.