ASP.NET CORE Study05

2023-11-30 19:05:55 浏览数 (2)

响应中 location 的设置

示例: 发送POST 请求,进行创建资源的操作。

注意的请求头中content-type 的设置,需要设置成 application/json 类型,并不一定需要json 类型的数据,但默认情况下使用的都是json传输数据,否则asp.net core 会返回 415 状态码。 同时请求体中 也要符合api 接口需要的格式,如果不符合,则会得到 400 的响应码。

在响应头中 包含 location 信息, 标识的新创建的资源的所在。

使用 代码示例:

代码语言:javascript复制
        // 这里使用 Name 属性为Action赋值,用于标识,一般跟Action方法名同称
		[HttpGet(template:"{CompanyId}", Name = nameof(GetCompany))]
        public async Task<IActionResult> GetCompany(Guid companyId)
        {
            var company = await _companyRepository.GetCompanyAsync(companyId);
            if (company == null)
            {
                return NotFound();
            }
            return Ok(_mapper.Map<CompanyDTO>(company));
        }
		// 创建资源的Action
        [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);
            // CreateRoute 方法 通过传递Action名称,以及一个匿名类 用于拼接完成的url,最后一个响应体的信息
            // 该 方法就会在响应头中添加上 location 信息,数值 则是 传递的Action 的访问路径 加上 匿名类设置的属性值,凭借成完整的url返回
            return CreatedAtRoute(nameof(GetCompany), new { companyId = returnDto.Id}, returnDto);
        }
ASP.NET Core 自定义模型绑定 modelbinder

在复杂的业务逻辑场景下,asp.net core 默认的模型绑定满足不了需要,需要自定义modelbinder

代码语言:javascript复制
    // 需要实现 IModelBinder 接口
	public class ArrayModelBinder : IModelBinder
    {	
    	// 实现 BindModelAsync 方法
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            // 验证传递进来的模型元数据是否是 Enumerable 的类型
            // 不是则返回失败
            if (!bindingContext.ModelMetadata.IsEnumerableType)
            {
                bindingContext.Result = ModelBindingResult.Failed();
                return Task.CompletedTask;
            }
            // 验证传递进来的模型元数据是否是空数据
            // 将模型中的数据转换成 String 类型
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ToString();
            // 验证数据是否是null,或空白字符串
            if (String.IsNullOrWhiteSpace(value))
            {
                bindingContext.Result = ModelBindingResult.Success(null);
                return Task.CompletedTask;
            }
            // 获取到模型的数据的具体类型
            var elementType = bindingContext.ModelType.GenericTypeArguments[0];
            // 获取一个转换器,将类型转换成指定类型的转换器
            var converter = TypeDescriptor.GetConverter(elementType);
            // 将模型的数据转换成的String 数据按,分割,通时使用转换器将String数据转换成 转换器指定的类型 的类型数据
            var values = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => converter.ConvertFromString(x.Trim())).ToArray();
            // 创建一个指定类型和长度的数组,数组的元素的数值是指定类型的默认值
            var typeValues = Array.CreateInstance(elementType, values.Length);
            // 将转换后的数据复制给新建的数组
            values.CopyTo(typeValues, 0);
            // 将放置转换后的数据的数组赋值给model
            bindingContext.Model = typeValues;
            // 操作成功
            bindingContext.Result = ModelBindingResult.Success(typeValues);
            return Task.CompletedTask;
        }
    }

上面的代码是将 用户传递的 类似 1,2,3,4 这样的字符串,通过模型绑定,转换成 IEnumable 类型的数据。

HTTP Options 方法

1、获取服务器支持的HTTP请求方法; 2、用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。 在 跨域时 CORS 中,使用很多。

Data Annotations 数据验证

asp.net core 内置提供的数据验证方式。 在 System.ComponmentModel.DataAnnotations 命名空间下通过的各种 Attribute,供于使用。

IValidatableObject 接口实现 数据验证

通过实现 IValidatableObject 接口 可以实现更为复杂的数据验证,可以对 数据模型类进行验证,跨属性的验证等。 使用:

代码语言:javascript复制
    // 与上面的Data Annotations位于同一命名空间下。
	public class EmployeeAdd : IValidatableObject
    {
        [Display(Name = "员工号"), Required(ErrorMessage = "{0}是必填项"), StringLength(10, MinimumLength = 10, ErrorMessage = "{0}的长度是{1}")]
        public String EmployeeNo { get; set; }
        [Display(Name = "名"), Required(ErrorMessage = "{0}是必填项"), MaxLength(50, ErrorMessage = "{0}的最大长度不超过{1}")]
        public String FirstName { get; set; }
        [Display(Name = "姓"), Required(ErrorMessage = "{0}是必填项"), MaxLength(50, ErrorMessage = "{0}的最大长度不超过{1}")]
        public String LastName { get; set; }
        [Display(Name = "性别")]
        public Gender Gender { get; set; }
        [Display(Name = "出生日期")]
        public DateTime DateOfBirth { get; set; }
		// 实现接口,实现方法,在方法中对类进行更复杂的验证
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (FirstName == LastName)
            {
                yield return new ValidationResult(errorMessage: "姓和名不能一致!", memberNames: new[] { nameof(FirstName), nameof(LastName)});
            }
        }
    }
自定义Attribute 数据验证

使用自定义 Attribute 也可以完成复杂的数据验证。 通过继承 ValidationAttribute 类,并重写 IsValid 方法来自定义 Attribute。 使用

代码语言:javascript复制
    // 继承 System.ComponmentModel.DataAnnotations 命名空间下的 ValidationAttribute类
	public class EmployeeNoMustFromFirstNameAttribute : ValidationAttribute
    {
    	// 重写 IsValid 方法
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
        	// 这里可以完成复杂的验证,
            // object value 是 当该attribute 使用在属性上时 可以通过该参数获取到具体的该属性数据
            // ValidationContext validationContext 当使用在 类上时,可以通过该参数获取到模型类数据
            var addDto = (EmployeeAddDto)validationContext.ObjectInstance;
            if (addDto.EmployeeNo == addDto.FirstName)
            {
                return new ValidationResult(errorMessage: "名称与编号不能一致", memberNames: new[] { nameof(EmployeeAddDto) });
            }
            return base.IsValid(value, validationContext);
        }

    }

注意: 一般情况下,asp.net core 内置的data annotations 验证的优先级比较好(可以简单的这样认为),当data annotation 验证报错时则后面的IValidatableObject 接口和自定义 Attribute 则不会在进行验证,这就是一个优先级的问题,而IValidatableObject 接口验证 和 自定义Attribute 的优先级基本一致。

0 人点赞