ASP。NET MVC4 Web API应用程序定义post方法来保存客户。 客户在POST请求体中以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"}

当前回答

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

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

首先验证请求

if (ModelState.IsValid)

然后使用序列化的数据。

Content = new StringContent(update.Status)

这里的“Status”是复杂类型中的一个字段。序列化是由。net完成的,不用担心。

其他回答

下面的代码返回json格式的数据,而不是xml - web API 2

在全局中放入以下一行。asax文件

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

编辑:31/10/2017

同样的代码/方法也适用于Asp。Net Core 2.0也是。主要的区别是,在asp.net核心中,web api控制器和Mvc控制器都被合并到一个控制器模型中。所以你的返回类型可能是IActionResult或者它的一个实现(例如:OkObjectResult)


Use

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 action方法参数

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 MVC6是最新的稳定版本,在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;
}

并发送模型(原始javascript对象,不是JSON格式)而不指定contentType属性值

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

模型绑定将适用于模型上的平面属性,而不适用于复杂类型/其他类型的属性。在本例中,Id和Name属性将正确地绑定到参数m,但Tags属性将是一个空列表。

如果您使用的是短版本$,也会出现同样的问题。post在发送请求时将使用默认的Content-Type。

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

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

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

首先验证请求

if (ModelState.IsValid)

然后使用序列化的数据。

Content = new StringContent(update.Status)

这里的“Status”是复杂类型中的一个字段。序列化是由。net完成的,不用担心。

@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")
}

1)在你的客户端,你可以给你发送http。在下面这样的字符串中提交请求

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)确保你的序列化字符串(这里的IndexInfo)变得像下面的结构在JsonConvert。步骤2中的反序列化对象命令

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";