Asp.net core 学习笔记 ( Web Api )

更新:2021-06-11

c# 的 property 是 PascalCase 而 js 是 camelCase 

所以在 form post 和 ajax 的时候经常会出问题. 以前我是让 c# 迁就 js 大家统一 camelCase

但是现在我觉得应该要让它们回归本质. 

当然 asp.net core 自然有帮忙解决这个问题, 默认情况下不管是 fromform 还是 frombody 前端传 camelCase 上来, 后端接收 PascalCase 是没有问题的, 然后返回 PascalCase 去到前端就是 camelCase 了

中间 asp.net core 都处理好了, 但是如果万一它没有匹配到的话。

我们也可以手动去配置一下

for json 的话用 

[JsonPropertyName("name_en")]

form post 的话用

[BindProperty(Name = "name_en")]

2 个可以一起用, 不冲突, 比如接收 form post 返回 json

更新: 2021-06-01

遇到一个 bug, 前端 submit form string value 是 '' empty, 后端记入的时候变成了 null

原来是 [fromform] 搞得鬼. 

因为前端有时候会 submit file 所以我用 fromform 打天下. 结果... 

https://stackoverflow.com/questions/44376540/asp-net-core-model-binding-how-to-get-empty-field-to-bind-as-a-blank-string

https://thomaslevesque.com/2018/09/04/handling-multipart-requests-with-json-and-file-uploads-in-asp-net-core/

https://github.com/aspnet/Mvc/issues/4988

默认情况下, 处理 form model binding 就是这样的. json 就不会. 

2 个 solution 一个是在 property 上面加 attribute

[DisplayFormat(ConvertEmptyStringToNull = false)]

另一个是在 startup.cs configure options (这个动作比较大, 不推荐)

 

更新 : 2020-02-21

前端传值的时候, 如果没有传某些属性该怎么处理比较好呢? 

假设要传一个 class 里面有一个 int 属性 

如果我们跑默认的配置的话, 在 controller 会收到 value 0

web api 在转换 json 时会弄好默认值. 

但如果 string, object, list  则不会处理, 会返回 error

c# 8 之后, 如果 string, object, list 不是 nullable 的话,我们是需要设置默认值的。

目前我的规范是, string 没给就放 "" 作为默认值, list = new List 作为默认,  object 就报错.

所以除了 object 基本上其它的都可以有默认值。

最近对 1-1 的 table 有了一个新规定,就是尽可能要有,所以我 object 这种情况下也可以 default value 给它哦.

如果想换默认的机制可以参考这里

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-5.0#customize-model-binding-with-input-formatters

.

更新: 2019-12-13

incomplete JSON response

多半是因为 response 了 entity, 然后被循环引用搞砸了. 

解决方案是 startup 调 config 

  services.AddMvc().AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });

但更好的是不要返回 entity, 因为返回值应该是 DTO 才对. 要经过处理丫, 权限丫

 

更新 : 2019-06-03 

web api 返回 json 的情况下默认会把属性 PascalCase 变成 camelCase 很贴心哦. 

如果你不喜欢可以修改它 

  services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())

但是这个对 odata 的 response 是没有影响的哦, odata 不会自动 camelCase 的.

asp.net core 把之前的 webapi 和 mvc 做了结合. 

mvc 既是 api. 

但是后来,又发现, api 确实有独到之处,所以又开了一些补助的方法.

namespace Project.Controllers
{
    public class PostForm
    {
        [Required]
        public IFormFile file { get; set; }
    }

    [ApiController] 
    [Route("api/[controller]")]
    public class ProductsController : ControllerBase 
    {
        private DB Db { get; set; }
        public ProductsController(DB db)
        {
            Db = db;
        }

        [HttpGet]
        public ActionResult<List<Product>> Get()
        {
            return Ok(Db.Products);
        }

        [HttpGet("{Id}")]
        [ProducesResponseType(400)]
        [ProducesResponseType(404)]
        public ActionResult<Product> GetById(string Id,[Required] string code)
        {
            return NotFound();            
        }

        [HttpPost]
        [ProducesResponseType(400)]
        public async Task<ActionResult<Product>> Post(Product product)
        {
            Db.Add(product);
            await Db.SaveChangesAsync();
            return Ok(product);
        }

        [HttpPost("upload")]
        [ProducesResponseType(400)]
        public ActionResult<string> Upload([FromForm] PostForm form)
        {
            return Ok("filename");
        } 
    }
}

继承的是 ControllerBase 而不是 MVC 常用的 Controller. Controller 会继承 ControllerBase

[ApiController], 使用标签 ApiController 会开启自动 model valid 检查, 自动 binding FromBody, FromQuery 等, 但 FromForm 还是要自己写哦 (默认 api 都是 json 的嘛) , 如果你担心它的智能,也可以完全自己写. 

或则把它某个智能关掉 . Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

[HttpPost("nextSegment")] 通过 http method 标签,我们可以很容易的写各做方法, 比如 get,post,put,delete, route 功能也包在内了真好呢. 

[ProducesResponseType] 这个标签主要功能是为了方便做 document, 配合 ActionResult<T> 泛型, 我们可以简单的表示正常情况下的返回,其余不正常情况使用 ProducesResponseType 来表示. 

通常是 404, 400 应该没有别的了吧.

原文地址:https://www.cnblogs.com/keatkeat/p/9297672.html