it-swarm-ko.tech

ASP.NET 코어 서버와 JSON을 연결하십시오.

.NET Core Web API 컨트롤러에서 HTTP 상태 코드를 사용하여 JSON을 반환하는 올바른 방법을 찾고 있습니다. 나는 이것을 다음과 같이 사용한다.

public IHttpActionResult GetResourceData()
{
    return this.Content(HttpStatusCode.OK, new { response = "Hello"});
}

이것은 4.6 MVC 응용 프로그램에 있었지만 .NET Core에서는 현재이 IHttpActionResult을 가지고있는 것 같지 않습니다. ActionResult을 (를) 사용하고 다음과 같이 사용하고 있습니다.

public ActionResult IsAuthenticated()
{
    return Ok(Json("123"));
}

그러나 아래 그림과 같이 서버의 응답이 이상합니다.

 enter image description here

Web API 2에서했던 것처럼 웹 API 컨트롤러가 JSON을 HTTP 상태 코드로 반환하기를 원합니다.

95
Rossco

JsonResult로 응답하는 가장 기본적인 버전은 다음과 같습니다.

// GET: api/authors
[HttpGet]
public JsonResult Get()
{
    return Json(_authorRepository.List());
}

그러나 이것은 자신의 응답 코드를 명시 적으로 처리 할 수 ​​없기 때문에이 문제에 도움이되지 않습니다.

상태 결과를 제어하는 ​​방법은 ActionResult 형식을 활용할 수있는 StatusCodeResult을 반환해야하는 것입니다.

예 :

// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authorRepository.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

위의 두 예제 모두 Microsoft 설명서에서 제공하는 훌륭한 가이드에서 나온 것입니다. Response Data Formatting


추가 재료

필자가 자주 겪게되는 문제는 VS의 "New Project"템플리트의 기본 구성을 사용하는 것보다 WebAPI를보다 세부적으로 제어하기를 원했기 때문입니다.

기본 사항 중 일부를 확인하십시오.

1 단계 : 서비스 구성

ASP.NET Core WebAPI가 상태 코드를 완전히 제어하면서 JSON 직렬화 된 객체로 응답하게하려면 Startup.cs에 일반적으로있는 ConfigureServices 메소드에 AddMvc() 서비스가 포함되어 있는지 확인해야합니다.

AddMvc()은 다른 요청 유형에 응답하면서 JSON 용 입력/출력 포매터를 자동으로 포함한다는 점에 유의해야합니다.

프로젝트에 전체 제어가 필요하고 WebAPI가 application/json를 비롯한 다양한 요청 유형에 대해 작동하고 다른 요청 유형 (예 : 표준 브라우저 요청)에 응답하지 않는 것처럼 서비스를 엄격하게 정의하려는 경우 다음 코드를 사용하여 수동으로 정의하십시오.

public void ConfigureServices(IServiceCollection services)
{
    // Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
    // https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

    services
        .AddMvcCore(options =>
        {
            options.RequireHttpsPermanent = true; // does not affect api requests
            options.RespectBrowserAcceptHeader = true; // false by default
            //options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

            //remove these two below, but added so you know where to place them...
            options.OutputFormatters.Add(new YourCustomOutputFormatter()); 
            options.InputFormatters.Add(new YourCustomInputFormatter());
        })
        //.AddApiExplorer()
        //.AddAuthorization()
        .AddFormatterMappings()
        //.AddCacheTagHelper()
        //.AddDataAnnotations()
        //.AddCors()
        .AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}

다른 serialization 형식 (protobuf, thrift 등)에 응답하려는 경우 사용자 지정 입력/출력 형식 지정자를 추가 할 수있는 방법도 포함되어 있습니다.

위의 코드는 대부분 AddMvc() 메소드의 복제본입니다. 그러나 우리는 각 "기본"서비스를 구현하기 위해 템플릿과 함께 선적 된 패키지 대신에 모든 서비스를 정의함으로써 자체적으로 서비스를 구현합니다. 코드 블록에 저장소 링크를 추가했거나 GitHub 저장소에서 AddMvc()를 체크 아웃 할 수 있습니다. .

기본값을 구현하지 않고 기본값을 "취소"하여이 문제를 해결하려고하는 몇 가지 지침이 있음을 기억하십시오 ... 우리가 현재 오픈 소스로 작업하고 있다는 점을 감안하면이 중복 작업, 나쁜 코드 및 솔직히 사라질 오래된 습관입니다. _


2 단계 : 컨트롤러 만들기

저는 질문을 정렬하기 위해 당신에게 정말로 똑바로 보여줄 것입니다.

public class FooController
{
    [HttpPost]
    public async Task<IActionResult> Create([FromBody] Object item)
    {
        if (item == null) return BadRequest();

        var newItem = new Object(); // create the object to return
        if (newItem != null) return Ok(newItem);

        else return NotFound();
    }
}

3 단계 : Content-TypeAccept을 확인하십시오.

request)의 Content-TypeAccept 헤더가 올바르게 설정되었는지 확인해야하며, JSON의 경우 application/json로 설정해야합니다.

WebAPI가 요청 헤더가 지정하는 것과 관계없이 JSON으로 응답하도록하려면 몇 가지 방법.

Way 1이전에 추천 한 기사 ( Formatting Response Data )에서 볼 수 있듯이 컨트롤러/액션 수준에서 특정 형식을 강요 할 수 있습니다. 개인적으로이 접근법이 마음에 들지 않지만 여기서는 완성을위한 것입니다 :

특정 형식 강제할 수있는 특정 동작에 대한 응답 형식을 제한하려면 [Produces] 필터를 적용 할 수 있습니다. [Produces] 필터는 특정 동작 (또는 컨트롤러)에 대한 응답 형식을 지정합니다. 대부분의 필터와 마찬가지로 액션, 컨트롤러 또는 전역 범위에 적용 할 수 있습니다.

[Produces("application/json")]
public class AuthorsController

[Produces] 필터는 응용 프로그램에 대해 다른 포맷터가 구성되어 있고 클라이언트가 사용 가능한 다른 형식을 요청하는 AuthorsController 헤더를 제공하더라도 Accept 내의 모든 액션이 JSON 형식의 응답을 반환하도록합니다.

Way 2내 선호하는 방법은 WebAPI가 요청 된 형식으로 모든 요청에 ​​응답하는 것입니다. 그러나 요청 된 형식을 받아들이지 않는 경우 후퇴기본값으로 즉 JSON)

먼저 옵션에 등록해야합니다 (앞에서 설명한 것처럼 기본 동작을 다시 작성해야 함)

options.RespectBrowserAcceptHeader = true; // false by default

마지막으로, 서비스 빌더에 정의 된 포매터의 목록을 간단히 재정렬함으로써 웹 호스트는 사용자가 목록의 맨 위에 위치하는 포맷터 (즉, 위치 0)를 기본값으로 사용합니다.

자세한 내용은이 .NET 웹 개발 및 도구 블로그 항목 을 참조하십시오.

129
Svek

가장 일반적인 상태 코드에 대해 미리 정의 된 메서드가 있습니다.

  • Ok(result)은 응답과 함께 200를 반환합니다.
  • CreatedAtRoute201 + 새 리소스 URL을 반환합니다.
  • NotFound404를 반환합니다.
  • BadRequest400 등을 반환합니다.

모든 방법 목록은 BaseController.csController.cs 를 참조하십시오.

그러나 정말로 StatusCode을 사용하여 사용자 정의 코드를 설정할 수는 있지만 실제로 코드를 읽기 쉽지 않으므로 코드를 반복하여 CreatedAtRoute과 같은 헤더를 설정해야합니다.

public ActionResult IsAuthenticated()
{
    return StatusCode(200, Json("123"));
}
41
Tseng

ASP.NET Core 2.0 을 사용하면 Web API (MVC와 통합되고 동일한 기본 클래스 Controller을 사용)에서 객체를 반환하는 가장 이상적인 방법은 무엇입니까?

public IActionResult Get()
{
    return new OkObjectResult(new Item { Id = 123, Name = "Hero" });
}

그것을주의해라

  1. 200 OK 상태 코드를 반환합니다 (Ok 유형의 ObjectResult입니다).
  2. 콘텐츠 협상을 수행합니다. 즉, 요청시 Accept 헤더를 기반으로 반환됩니다. 요청시 Accept: application/xml가 전송되면 XML으로 반환됩니다. 아무것도 보내지 않으면 JSON이 기본값입니다.

특정 상태 코드 를 보내야하는 경우 대신 ObjectResult 또는 StatusCode을 사용하십시오. 둘 다 똑같은 일을하고 컨텐츠 협상을 지원합니다.

return new ObjectResult(new Item { Id = 123, Name = "Hero" }) { StatusCode = 200 };
return StatusCode( 200, new Item { Id = 123, Name = "Hero" });

구체적으로 JSON 로 반환하려는 경우 몇 가지 방법이 있습니다.

//GET http://example.com/api/test/asjson
[HttpGet("AsJson")]
public JsonResult GetAsJson()
{
    return Json(new Item { Id = 123, Name = "Hero" });
}

//GET http://example.com/api/test/withproduces
[HttpGet("WithProduces")]
[Produces("application/json")]
public Item GetWithProduces()
{
    return new Item { Id = 123, Name = "Hero" };
}

그것을주의해라

  1. 두 가지 방법 모두 JSON을 두 가지 방법으로 시행합니다.
  2. 둘 다 내용 협상을 무시합니다.
  3. 첫 번째 메서드는 JSON에 특정 serializer Json(object)을 적용합니다.
  4. 두 번째 방법은 Produces() (ResultFilter) 속성을 사용하여 contentType = application/json

그 (것)들에 관하여 더 많은 것을 공식 문서 에서 읽으십시오. 여기 필터 에 대해 자세히 알아보십시오.

샘플에 사용되는 간단한 모델 클래스

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}
25
Arghya C

내가 생각해 낸 가장 쉬운 방법은 다음과 같습니다.

return new JsonResult(result)
{
    StatusCode = 201 // Status code here 
};
14
Gerald Hughes

이것이 나의 가장 쉬운 해결책이다 :

public IActionResult InfoTag()
{
    return Ok(new {name = "Fabio", age = 42, gender = "M"});
}

또는

public IActionResult InfoTag()
{
    return Json(new {name = "Fabio", age = 42, gender = "M"});
}
6
Fabio

Enum을 사용하여 404/201 상태 코드를 사용하는 대신

     public async Task<IActionResult> Login(string email, string password)
    {
        if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(password))
        { 
            return StatusCode((int)HttpStatusCode.BadRequest, Json("email or password is null")); 
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, Json("Invalid Login and/or password"));

        }
        var passwordSignInResult = await _signInManager.PasswordSignInAsync(user, password, isPersistent: true, lockoutOnFailure: false);
        if (!passwordSignInResult.Succeeded)
        {
            return StatusCode((int)HttpStatusCode.BadRequest, Json("Invalid Login and/or password"));
        }
        return StatusCode((int)HttpStatusCode.OK, Json("Sucess !!!"));
    }
2
ram dev

Asp Net Core Api 응용 프로그램에서 ObjectResult에서 확장되는 클래스를 만들고 내용 및 상태 코드를 사용자 지정하는 많은 생성자를 제공합니다. 그런 다음 모든 Controller 액션은 costructor 중 하나를 적절하게 사용합니다. 제 구현을 다음에서 볼 수 있습니다 : https://github.com/melardev/AspNetCoreApiPaginatedCrud

https://github.com/melardev/ApiAspCoreEcommerce

다음은 클래스의 모양입니다 (전체 코드를 보려면 내 레포로 이동하십시오).

public class StatusCodeAndDtoWrapper : ObjectResult
{



    public StatusCodeAndDtoWrapper(AppResponse dto, int statusCode = 200) : base(dto)
    {
        StatusCode = statusCode;
    }

    private StatusCodeAndDtoWrapper(AppResponse dto, int statusCode, string message) : base(dto)
    {
        StatusCode = statusCode;
        if (dto.FullMessages == null)
            dto.FullMessages = new List<string>(1);
        dto.FullMessages.Add(message);
    }

    private StatusCodeAndDtoWrapper(AppResponse dto, int statusCode, ICollection<string> messages) : base(dto)
    {
        StatusCode = statusCode;
        dto.FullMessages = messages;
    }
}

당신이 당신의 물건으로 대체 한 기지 (dto)를 주목하십시오. 그러면 당신은 잘 가야합니다.

0
Melardev

여기에서 찾은 멋진 답변과 StatusCode(whatever code you wish) 참조 하여이 return 문을 사용해 보았습니다.

return Ok(new {
                    Token = new JwtSecurityTokenHandler().WriteToken(token),
                    Expiration = token.ValidTo,
                    username = user.FullName,
                    StatusCode = StatusCode(200)
                });
0
Oge Nwike