如何将JSON POST数据作为对象传递给Web API方法?

2020/10/03 19:01 · javascript ·  · 0评论

ASP.NET MVC4 Web API应用程序定义了发布方法以节省客户。客户在POST请求正文中以json格式传递。post方法中的Customer参数包含属性的空值。

如何解决此问题,以便过帐的数据将作为客户对象传递?

如果可能的话,应该使用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"}

编辑:31/10/2017

同样的代码/方法也适用于Asp.Net Core 2.0主要区别在于,在asp.net核心中,Web 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"
    });
});

结果

在此处输入图片说明

contentType属性告诉服务器我们正在以JSON格式发送数据。由于我们发送了JSON数据结构,因此模型绑定将正确进行。

如果检查ajax请求的标头,则可以看到该Content-Type值设置为application/json

如果未明确指定contentType,它将使用默认的内容类型为 application/x-www-form-urlencoded;


编辑于2015年11月以解决评论中提出的其他可能问题

发布复杂对象

假设您有一个复杂的视图模型类作为Web 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;}
}

和您的Web API端点就像

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中,Web api控制器和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]属性修饰Web api方法参数

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

并在不指定contentType属性值的情况下发送模型(原始javascript对象,非JSON格式)

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

模型绑定将适用于模型上的平面属性,不适用于类型为复杂/另一种类型的属性。在我们的示例中,IdName属性将正确绑定到参数m,但是Tags属性将是一个空列表。

如果使用的是简短版本,则会发生相同的问题,该简短版本$.post在发送请求时将使用默认的Content-Type。

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

在webapi中使用POST可能很棘手!想要添加到已经正确的答案。

由于处理GET是微不足道的,因此将特别关注POST。我认为没有人会四处寻找解决webapis GET问题的方法。无论如何..

如果您的问题是-在MVC Web Api中,如何-使用除通用HTTP动词之外的自定义操作方法名称?-执行多个帖子?-发布多种简单类型?-通过jQuery发布复杂类型?

然后,以下解决方案可能会有所帮助:

首先,要在Web API中使用自定义操作方法,请添加Web 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”))分配自定义名称,等等。下面第四点将介绍jQuery。

第三,首先,不可能在一个动作中发布多个SIMPLE类型。此外,还有一种特殊的格式可以发布单个简单类型(除了以查询字符串或REST样式传递参数之外)。这就是我用Rest Clients(例如Fiddler和Chrome的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":"na@Turbo.Tina"}

PS:注意到特殊的语法吗?

http://forums.asp.net/t/1883467.aspx?+I+try+to+Post+to+my+Web+Api++

无论如何,让我们克服这个故事。继续:

第四,通过jQuery发布复杂类型,当然,$ .ajax()会迅速发挥作用:

假设操作方法接受具有id和名称的Person对象。因此,从javascript:

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

以上所有对我有用!!干杯!

我一直在玩这个游戏,发现了一个相当奇怪的结果。假设您在C#中的类具有公共属性,如下所示:

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

那么您必须按照Shyju的建议执行JSON.stringify技巧,并按以下方式调用它:

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

但是,如果您像这样在类中定义getter和setter:

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

我不太确定这里发生了什么,但是它看起来像框架中的错误(功能?)。可能是不同的绑定方法调用了不同的“适配器”,而用于application / json的适配器一种使用公共属性,而用于表单编码数据的适配器则没有。

我不知道这将是最佳实践。

使用JSON.stringify()获取JSON格式的字符串,请确保在进行AJAX调用时传递以下提到的属性:

  • contentType:“ application / json”

下面是给出jquery代码以对asp.net Web API进行ajax发布:

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

确保您的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";
}

以下代码以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);
@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")
}

微软给出了一个很好的例子:

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

首先验证请求

if (ModelState.IsValid)

而不是使用序列化的数据。

Content = new StringContent(update.Status)

“状态”是复杂类型的字段。序列化是由.NET完成的,无需担心。

1)在您的客户端,您可以使用以下字符串向您发送http.post请求

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

2)然后在您的Web 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)在第2步中的JsonConvert.DeserializeObject命令之前,确保序列化的字符串(此处为IndexInfo)类似于以下结构

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";
本文地址:http://javascript.askforanswer.com/ruhejiangjson-postshujuzuoweiduixiangchuandigeiweb-apifangfa.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!