[javascript] json POST 데이터를 웹 API 메소드에 객체로 전달하는 방법은 무엇입니까?

ASP.NET MVC4 웹 API 응용 프로그램은 고객을 저장하기 위해 사후 방법을 정의합니다. 고객은 POST 요청 본문에서 json 형식으로 전달됩니다. 사후 메소드의 고객 매개 변수에 특성의 널값이 포함되어 있습니다.

게시 된 데이터가 고객 객체로 전달되도록이 문제를 해결하는 방법은 무엇입니까?

가능한 경우 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"}



답변

편집 : 2017 년 10 월 31 일

동일한 코드 / 접근 방식이 Asp.Net Core 2.0 에서도 작동 합니다. 가장 큰 차이점은 asp.net 코어에서 웹 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 월 편집

복잡한 객체 게시

다음과 같이 웹 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 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에서는 웹 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 :)
});

모델 바인딩은 일부 속성에는 작동하지만 전부는 아닙니다! 왜 ?

웹 API 메소드 매개 변수를 [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);
});

모델 바인딩은 유형이 복잡한 / 다른 유형의 속성이 아니라 모델의 플랫 속성에 적용됩니다. 우리의 경우, 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를 통해 복잡한 유형을 게시 하시겠습니까?

그러면 다음 해결책이 도움이 될 수 있습니다.

먼저 웹 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”)]을 사용하여 사용자 정의 이름 등을 지정하십시오. 아래 네 번째 지점에서 jQuery가 나타납니다.

셋째, 우선 단일 작업으로 여러 SIMPLE 유형을 게시 할 수 없습니다. 또한 쿼리 문자열이나 REST 스타일로 매개 변수를 전달하는 것 외에도 단일 단순 유형 을 게시 하는 특수 형식 이 있습니다. 이것은 Fiddler 및 Chrome의 고급 REST 클라이언트 확장과 같은 Rest Client로 머리를 두드리고 거의 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를 통해 을 물론 $ .ajax ()가 즉시 역할을 수행하게됩니다.

액션 메소드가 아이디와 이름을 가진 Person 객체를 받아 들인다 고하자. 따라서 자바 스크립트에서 :

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

그러나 클래스에 게터와 세터를 다음과 같이 정의하면

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 용 어댑터는 공용 속성과 작동하지만 양식 인코딩 된 데이터 용 어댑터는 작동하지 않습니다.

그래도 모범 사례로 간주 될 생각은 없습니다.


답변

JSON 형식으로 문자열을 가져 오려면 JSON.stringify () 를 사용하십시오. AJAX 호출을 수행하는 동안 언급 된 속성 아래에 전달해야합니다.

  • contentType : ‘application / json’

다음은 asp.net 웹 API에 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);
    }
});


답변

WebAPI 서비스가 전달중인 JSON과 일치하는 구조를 가진 강력한 유형의 객체를 기대하고 있는지 확인하십시오. 그리고 POST중인 JSON을 문자열로 묶어야합니다.

AngluarJS를 사용하는 JavaScript는 다음과 같습니다.

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


답변

다음 코드는 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);


답변

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