The return type of Action in ASP.NET Core

Before Asp.net Core, all Action return values ​​were ActionResult, and Json (), File () and other methods returned ActionResult subclasses. And after Core merged MVC with WebApi, the Action return value system has also changed a lot.

ActionResult class

The ActionResult class is the most commonly used return value type. Basically follow the previous Asp.net MVC set of things, use it in most cases is no problem. For example, use it to return to view, return to json, return to file, etc. If it is asynchronous, use Task

    public class TestController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult MyFile()
        {
            return File(new byte[] { }, "image/jpg");
        }

        public ActionResult MyJson()
        {
            return Json(new { name = "json" });
        }

        public ActionResult Ok()
        {
            return Ok();
        }
    }

IActionResult interface

The ActionResult class implements the IActionResult interface, so IActionResult can be used in place of ActionResult. If it is also asynchronous, use the Task package as the return value.

   public class ITestController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult MyFile()
        {
            return File(new byte[] { }, "image/jpg");
        }

        public IActionResult MyJson()
        {
            return Json(new { name = "json" });
        }

        public IActionResult HttpOk()
        {
            return Ok();
        }

        public async Task<IActionResult> AsyncCall()
        {
            await Task.Delay(1000);

            return Content("ok");
        }
    }

Return directly to POCO

Asp.net Core's Controller Action can take POCO type (actually not necessarily POCO class, it can be any type, but generally returns POCO class such as viwemodel when used) as the return value, not necessarily ActionResult or IActionResult. The Asp.net Core framework will help us automatically serialize and return to the front end. By default, json serialization is used. If it is also asynchronous, use the Task package as the return value.

   public class Person
    {
        public string Name { get; set; }

        public string Sex { get; set; }
    }

    public class ITestController : Controller
    {

          public Person GetPerson()
        {
            return new Person { Name = "abc", Sex = "f" };
        }

        public async Task<List<Person>> GetPersons()
        {
            await Task.Delay(1000);

            return new List<Person> {
            new Person { Name = "abc", Sex = "f" },
            new Person { Name = "efg", Sex = "m" }
            };
        }
    }

ActionResult <T> generic class

When we design restful webapi system, we are used to using POCO as the return value. For example, we design an API to get Person. Get person 001 through / person / 001 url.

    [Route("[controller]")]
    public class PersonController : Controller
    {
        IPersonRepository _repository;
        PersonController(IPersonRepository repository) 
        {
            _repository = repository;
        }

        [HttpGet("{id}")]
       public Person Get(string id)
        {
            return _repository.Get(id);
        }
    }

This method seems to be no problem, but there is actually a small problem. If the repository.Get method does not find the data based on the id, it will return null. If null is used as the return value of Action, the final frame will be converted to 204 http status code.

204 means No Content. As a restful api, the semantics of 204 will be problematic here. The more suitable status code here is 404 NOT FOUND. Then let's change it:

        [HttpGet("{id}")]
       public Person Get(string id)
        {
            var person = _repository.Get(id);
            if (person == null)
            {
                Response.StatusCode = 404;
            }

            return person;
        }

Now if the person data cannot be found, the system will return 404 Not Found.

But this is obviously not elegant enough, because ControllerBase has a built-in NotFoundResult NotFound () method. The code looks clearer and clearer using this method. Continue to change:

        [HttpGet("{id}")]
       public Person Get(string id)
        {
            var person = _repository.Get(id);
            if (person == null)
            {
                return NotFound();
            }
            return person;
        }

Unfortunately, this code VS will prompt an error. Because the return value type is inconsistent. The return value of the method signature is Person, but NotFoundResult will be returned within the method and Person will be returned once.

To solve this problem, it is time for ActionResult <T> to appear. We continue to change:

        [HttpGet("{id}")]
       public ActionResult<Person> Get(string id)
        {
            var person = _repository.Get(id);
            if (person == null)
            {
                return NotFound();
            }

            return person;
        }

Now VS will not report an error, it can work normally after running it. But it is also very strange to think about it. Why is it that the return value type is changed to ActionResult <Person> and it is not wrong? Obviously the return value type is not consistent with the method signature?

In-depth ActionResult <T>

Following the above question, let's take a look at the inside of ActionResult:

see here to understand that there are two implicit operator methods built into the original ActionResult <T>. implicit operator is used to declare implicit type conversion.

public static implicit operator ActionResult<TValue>(ActionResult result); 

Indicates that the ActionResult type can be converted to the ActionResult <TValue> type.

public static implicit operator ActionResult<TValue>(TValue value)

Indicates that the TValue type can be converted to ActionResult <TValue> type.

Because of these two methods, an automatic type conversion is performed when the ActionResult or TValue type is assigned to ActionResult <T>. So VS will not report an error here.

to sum up

  1. Most of the time the return value of Action can use ActionResult / IActionResult
  2. When designing restful APIs, you can directly use the POCO class as the return value
  3. If you want to design an action that supports both the return value of the POCO class or the ActionResult class as the return value, you can use ActionResult <T> as the return value
  4. The reason why ActionResult <T> can support two types of return value types is because the implicit operator has built-in 2 implicit conversion methods

Guess you like

Origin www.cnblogs.com/kklldog/p/aspnetcore-actionresult.html