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);
});
모델 바인딩은 유형이 복잡한 / 다른 유형의 속성이 아니라 모델의 플랫 속성에 적용됩니다. 우리의 경우, 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);
});
답변
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")
}