• .net core RESTful Api笔记③


    HTTP安全性和幂等性

    安全性指的是方法执行后并并不会改变资源的表述

    幂等性指的是方法无论执行多少次都会得到同样的结果

     这里创建Company资源:

            [HttpPost]
            public async Task<ActionResult<CompanyDto>> CreateCompany([FromBody]CompanyAddDto company) 
            {
                var entity = _mapper.Map<Company>(company);
                _companyRepository.AddCompany(entity);
                await _companyRepository.SaveAsync();
    
                var returnDto = _mapper.Map<CompanyDto>(entity);
    
                return CreatedAtRoute(nameof(GetCompanies),new { companyId= returnDto.Id},returnDto);
            }

    里面的CreatedAtRoute返回符合resultful风格,并且需要新的添加dto,映射的addmap也要添加。

    为了保证重构方便,而且读取的dto资源不够

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Models
    {
        public class CompanyAddDto
        {
            public string Name { get; set; }
            public string introduction { get; set; }
        }
    }

    添加employee资源:

    也是和上面比较类似

     [HttpPost]
            public async Task<ActionResult<EmployeeDto>> CreaterEmployeeForCompany(Guid companyId,EmployeeAddDto employee) 
            {
                if (!await this.companyRepository.CompanyExistsAsync(companyId)) 
                {
                    return NotFound();
    
                }
                var entity = mapper.Map<Employee>(employee);
    
                companyRepository.AddEmployee(companyId,entity);
                await companyRepository.SaveAsync();
    
                var dtoToReturn = mapper.Map<EmployeeDto>(entity);
                return CreatedAtRoute(nameof(GetemployesFromCompany),new {CompanyId= companyId, employeeId= dtoToReturn.Id }, dtoToReturn);
            }

    AddDto:

    using Rountion.API.Eneities;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Models
    {
        public class EmployeeAddDto
        {
            public string EmployeeNo { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public Gender Gender { get; set; }
            public DateTime DateOfBirth { get; set; }
        }
    }

    同时创建父子资源:

    修改CompanyAddDto:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Models
    {
        public class CompanyAddDto
        {
            public string Name { get; set; }
            public string introduction { get; set; }
            public ICollection<EmployeeAddDto> Employee { get; set; } = new List<EmployeeAddDto>();
        }
    }

    结果:

     创建多个资源:

    controller:

    using AutoMapper;
    using Microsoft.AspNetCore.Mvc;
    using Rountine.API.Models;
    using Rountine.API.Services;
    using Rountion.API.Eneities;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Controllers
    {
        [ApiController]
        [Route("api/companycollections")]
        public class CompanyCollectionsController:ControllerBase
        {
            private readonly IMapper _mapper;
            private readonly ICompanyRepository _companyRepository;
            public CompanyCollectionsController(ICompanyRepository companyRepository, IMapper mapper) 
            {
                _mapper = mapper??throw new ArgumentException(nameof(mapper));
                _companyRepository = companyRepository?? throw new ArgumentException(nameof(companyRepository));
            }
            [HttpPost]
            public async Task<ActionResult<IEnumerable<CompanyDto>>> CreateCompanyCollections(IEnumerable<CompanyAddDto> companies) 
            {
                var companyEntities = _mapper.Map<IEnumerable<Company>>(companies);
                foreach (var company in companyEntities) 
                {
                    _companyRepository.AddCompany(company);
                }
                await _companyRepository.SaveAsync();
                return Ok();
            }
        }
    }

     这里返回时200,正常的应该返回201,所以这里还需要修改下

    修改方式也比较麻烦:

    controller:里面修改创建并添加了查询保证201状态码和返回添加的内容

    using AutoMapper;
    using Microsoft.AspNetCore.Mvc;
    using Rountine.API.Helpers;
    using Rountine.API.Models;
    using Rountine.API.Services;
    using Rountion.API.Eneities;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Controllers
    {
        [ApiController]
        [Route("api/companycollections")]
        public class CompanyCollectionsController : ControllerBase
        {
            private readonly IMapper _mapper;
            private readonly ICompanyRepository _companyRepository;
            public CompanyCollectionsController(ICompanyRepository companyRepository, IMapper mapper)
            {
                _mapper = mapper ?? throw new ArgumentException(nameof(mapper));
                _companyRepository = companyRepository ?? throw new ArgumentException(nameof(companyRepository));
            }
    
            [HttpGet("{ids}",Name=nameof(GetCompanyCollection))]
            public async Task<IActionResult> GetCompanyCollection(
                [FromRoute]
                [ModelBinder(BinderType=typeof(ArrayModelBinder))]IEnumerable<Guid> ids) 
            {
                if (ids == null) 
                {
                    return BadRequest();
                }
                var entities = await _companyRepository.GetCompaniesAsync(ids);
    
                if (ids.Count() != entities.Count()) 
                {
                    return NotFound();
                }
                var dtotoreturn = _mapper.Map<IEnumerable<CompanyDto>>(entities);
                return Ok(dtotoreturn);
            }
    
            [HttpPost]
            public async Task<ActionResult<IEnumerable<CompanyDto>>> CreateCompanyCollections(IEnumerable<CompanyAddDto> companies) 
            {
                var companyEntities = _mapper.Map<IEnumerable<Company>>(companies);
                foreach (var company in companyEntities) 
                {
                    _companyRepository.AddCompany(company);
                }
                await _companyRepository.SaveAsync();
                var dtosToReturn = _mapper.Map<IEnumerable<CompanyDto>>(companyEntities);
    
                var idsString = string.Join(",",dtosToReturn.Select(x=>x.Id));
    
                return CreatedAtRoute(nameof(GetCompanyCollection),new { ids = idsString }, dtosToReturn);
            }
        }
    }

    这里需要将传入的ids转化成IEnumerable<Guid>所以需要自定义一个model类型将传入的转化成guid

    ArrayModelBinder:

    using Microsoft.AspNetCore.Mvc.ModelBinding;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Reflection;
    using System.Threading.Tasks;
    
    namespace Rountine.API.Helpers
    {
    
        public class ArrayModelBinder : IModelBinder
        {
            public Task BindModelAsync(ModelBindingContext bindingContext)
            {
                if (!bindingContext.ModelMetadata.IsEnumerableType) 
                {
                    bindingContext.Result = ModelBindingResult.Failed();
                    return Task.CompletedTask;
                }
                var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ToString();
                if (string.IsNullOrEmpty(value)) 
                {
                    bindingContext.Result = ModelBindingResult.Success(null);
                    return Task.CompletedTask;
                }
                var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
                var converter = TypeDescriptor.GetConverter(elementType);
                var values = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x=>converter.ConvertFromString(x.Trim())).ToArray() ;
    
                var typedValues = Array.CreateInstance(elementType,values.Length);
                values.CopyTo(typedValues,0);
                bindingContext.Model = typedValues;
    
                bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
                return Task.CompletedTask;
            }
        }
    }

    请求:

  • 相关阅读:
    if..endif 语法
    WordPress程序流程分析
    php锁表
    jQuery入门必须掌握的一些API
    集合栈
    回文链表
    链式A+B
    链表分割
    访问单个节点的删除
    链表中倒数第k个结点
  • 原文地址:https://www.cnblogs.com/liuyang95/p/13206054.html
Copyright © 2020-2023  润新知