it-swarm.asia

كيفية اجتياز json POST البيانات إلى واجهة برمجة تطبيقات الويب ككائن؟

يحدد تطبيق ASP.NET MVC4 Web API طريقة النشر لحفظ العميل. يتم تمرير العميل بتنسيق json في POST نص الطلب. تحتوي معلمة العميل في طريقة النشر على قيم فارغة للخصائص.

كيفية إصلاح ذلك بحيث يتم تمرير البيانات المنشورة ككائن عميل؟

إن أمكن ، Content-Type: application/x-www-form-urlencoded يجب أن يستخدم لأنني لا أعرف كيفية تغييره في طريقة javascript التي يتم نشرها.

مراقب:

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"}
276
Andrus

EDIT: 31/10/2017

نفس الكود/المنهج سوف يعمل لصالح Asp.Net Core 2.0 كذلك. الفرق الرئيسي هو ، في asp.net core ، يتم دمج كل من وحدات تحكم api على الويب ووحدات التحكم Mvc معًا في طراز وحدة التحكم الفردية. لذلك قد يكون نوع الإرجاع الخاص بك IActionResult أو أحد تطبيقه (مثال: OkObjectResult)


استعمال

contentType:"application/json"

تحتاج إلى استخدام طريقة JSON.stringify لتحويلها إلى سلسلة JSON عند إرسالها ،

وسيقوم رابط النموذج بربط بيانات json بالكائن المدرسي.

الكود أدناه سوف يعمل بشكل جيد (تم اختباره)

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

نتيجة

enter image description here

تخبر خاصية contentType الخادم بأننا نرسل البيانات بتنسيق JSON. منذ أن أرسلنا بنية بيانات JSON ، سيحدث ربط النموذج بشكل صحيح.

إذا قمت بفحص رؤوس طلب ajax ، يمكنك أن ترى أن قيمة Content-Type تم تعيينها على أنها application/json.

إذا لم تحدد محتوى نوع صراحة ، فسيستخدم نوع المحتوى الافتراضي الذي هو application/x-www-form-urlencoded;


تعديل في نوفمبر 2015 لمعالجة المشكلات المحتملة الأخرى التي أثيرت في التعليقات

نشر كائن معقد

دعنا نقول أن لديك فئة نموذج عرض معقدة كمعلمة طريقة عمل api على الويب مثل هذا

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;}
}

ونقطة النهاية api الويب الخاص بك هو مثل

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewMode 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 ، توارث كل من وحدات التحكم api Web ووحدات التحكم 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 :)
});

يعمل ربط النموذج لبعض الخصائص ، ولكن ليس كل شيء! لماذا ا ؟

إذا لم تقم بتزيين معلمة أسلوب api على الويب باستخدام سمة [FromBody]

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

وإرسال النموذج (كائن javascript raw ، وليس بتنسيق JSON) دون تحديد قيمة خاصية contentType

$.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);
});
494
Shyju

قد يكون العمل مع POST في webapi أمرًا صعبًا! أود أن أضيف إلى الإجابة الصحيحة بالفعل ..

سوف تركز بشكل خاص على POST لأن التعامل مع GET أمر تافه. لا أعتقد أن الكثيرين سيبحثون حول حل مشكلة مع GET باستخدام webapis. على أي حال..

إذا كان سؤالك هو - في MVC Web Api ، كيفية استخدام أسماء طريقة الإجراء المخصص بخلاف أفعال HTTP العامة؟ - أداء وظائف متعددة؟ - نشر أنواع بسيطة متعددة؟ - نشر أنواع معقدة عبر مسج؟

ثم قد تساعد الحلول التالية:

أولاً ، لاستخدام Custom أساليب الإجراء في Web API ، أضف مسار api على الويب كـ:

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")] لتعيين أسماء مخصصة ، وما إلى ذلك. سيأتي إلى مسج في النقطة الرابعة أدناه

ثالثًا ، أولاً ، نشر متعددةSIMPLEأنواع في إجراء واحد غير ممكن. علاوة على ذلك ، يوجد تنسيق خاص لنشر حتى نوع بسيط واحد (بصرف النظر عن تمرير المعلمة في سلسلة الاستعلام أو REST النمط). كانت هذه هي النقطة التي جعلتني أضرب رأسي مع Rest Clients (مثل Fiddler و Chrome's Advanced REST امتداد العميل _) والبحث حول الويب لمدة 5 ساعات تقريبًا ، في نهاية المطاف ، أثبت عنوان URL التالي أنه مفيد. هل اقتبس المحتوى ذي الصلة للرابط قد ينتهي!

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

ملاحظة: لاحظت {غريبة بناء الجملة؟

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

على أي حال ، دعونا نتغلب على هذه القصة. المضي قدما:

الرابعة ، نشر أنواع معقدة عبر jQuery ، فكورسي ، $ .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;
}

كل ما سبق ، عملت لي! في صحتك!

66
Vaibhav

لقد كنت ألعب مع هذا واكتشفت نتيجة غريبة إلى حد ما. لنفترض أن لديك خصائص عامة في صفك في C # مثل هذا:

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

ثم يجب عليك القيام بالخدعة JSON.stringify كما اقترح Shyju ونسميها هكذا:

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

ومع ذلك ، إذا قمت بتحديد getters و setters في فصلك مثل هذا:

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

لست متأكدًا مما يحدث هنا ، لكن يبدو أنه خطأ (ميزة؟) في الإطار. يفترض أن أساليب الربط المختلفة تستدعي "محولات" مختلفة ، وبينما يعمل مهايئ التطبيق/json one مع الخصائص العامة ، فإن المحول الخاص بالبيانات المشفرة للنماذج لا يعمل.

ليس لدي أي فكرة والتي تعتبر أفضل الممارسات رغم ذلك.

10
Andy

استخدم ال JSON.stringify () للحصول على السلسلة بتنسيق JSON ، تأكد من أنه أثناء إجراء AJAX ندعوك تمر أدناه السمات المذكورة:

  • contentType: 'application/json'
  • نوع البيانات: 'json'

يوجد أدناه رمز jquery لإجراء مكالمة نشر من ajax إلى asp.net web api:

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',
    dataType: 'json',
    data: product,
    success: function (data, status, xhr) {
        alert('Success!');
    },
    error: function (xhr, status, error) {
        alert('Update Error occurred - ' + error);
    }
});
1
Dilip Nannaware

تأكد من أن خدمة WebAPI تتوقع كائنًا مكتوبًا بقوة بهيكل يطابق JSON الذي تمر به. وتأكد من توحيد JSON الذي تقوم بنشره.

إليكم JavaScript (باستخدام 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
scott janson

1) في جانب العميل الخاص بك ، يمكنك إرسال طلب http.post إليك في السلسلة كما يلي

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

2) ثم في وحدة تحكم الويب api يمكنك إلغاء تسلسلها

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

3) يجب أن تكون فئة ApiReceivedListOfObjects كما يلي

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""
        }
        ]
    }";
0
Mahdi ghafoorian

اتباع التعليمات البرمجية لإرجاع البيانات بتنسيق json ، بدلاً من xml -Web API 2: -

ضع السطر التالي في ملف Global.asax

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
0
UJS
@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
Debendra Dash

أعطت 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)

هنا "الحالة" هو حقل في نوع معقد. يتم إجراء تسلسل بواسطة .NET ، ولا داعي للقلق بشأن ذلك.

0
FrankyHollywood