Gri*_*der 22 .net asp.net-web-api
例如,有一个Web Api动作方法:
public HttpMessageResponse Post(UserDto userDto)
{
if (!this.ModelState.IsValid)
{
return this.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, this.ModelState);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
客户端发送以下请求:
HTTP POST: /api/user
{ "username": "me", "password": "Pa$sw0rd" }
Run Code Online (Sandbox Code Playgroud)
得到回应:
HTTP 201/Created:
{ "message": "Your request is invalid.",
"modelState": { "userDto.Password": "Your password is too strong." } }
Run Code Online (Sandbox Code Playgroud)
默认情况下,action方法通过在模型错误前加上action方法中使用的参数名称来公开实现细节.如果客户端应用程序在清理模型错误时硬编码此前缀名称,然后服务器端代码更改(例如,您更换了Post(UserDto userDto)签名Post(UserDto dto))并且所有客户端应用程序停止工作,该怎么办?
这就是为什么你需要确保在服务器端删除这个前缀.问题是,如何正确地做到这一点,而不会使事情复杂化.例如,您可以创建自定义序列化程序并在序列化期间删除这些前缀.但是为了做到这一点,你需要知道模型参数的名称,调用代码可能看起来像这样:
public HttpMessageResponse Post(UserDto userDto)
{
if (!this.ModelState.IsValid)
{
return this.Request.CreateCustomErrorResponse(
HttpStatusCode.BadRequest, this.ModelState, modelName: "userDto");
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
dma*_*son 45
第一部分:
返回给客户端的错误消息也不应包含这些前缀
我同意将参数名称作为所有模型状态错误的前缀并不是很好的行为.幸运的是,具有此行为的服务是可替换的.你只需要一个自定义的IBodyModelValidator.这是它的样子(使用Decorator模式让默认服务完成大部分工作):
public class PrefixlessBodyModelValidator : IBodyModelValidator
{
private readonly IBodyModelValidator _innerValidator;
public PrefixlessBodyModelValidator(IBodyModelValidator innerValidator)
{
if (innerValidator == null)
{
throw new ArgumentNullException("innerValidator");
}
_innerValidator = innerValidator;
}
public bool Validate(object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, string keyPrefix)
{
// Remove the keyPrefix but otherwise let innerValidator do what it normally does.
return _innerValidator.Validate(model, type, metadataProvider, actionContext, String.Empty);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,用你的包装默认服务:
config.Services.Replace(typeof(IBodyModelValidator), new PrefixlessBodyModelValidator(config.Services.GetBodyModelValidator()));
Run Code Online (Sandbox Code Playgroud)
第二部分:
elso用"错误"替换"modelState"
它当前说"modelState"的原因是您当前的代码:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Run Code Online (Sandbox Code Playgroud)
有效地做了以下事情:
HttpError error = new HttpError(ModelState, false);
return Request.CreateResponse(HttpStatusCode.BadRequest, error);
Run Code Online (Sandbox Code Playgroud)
由于HttpError是序列化的,并且它有一个名为"ModelState"的属性,这就是你在响应中看到的.
如果需要不同的属性名称,可以使用自定义错误类:
public class PrettyHttpError
{
public PrettyHttpError(ModelStateDictionary modelState)
{
Message = "Your request is invalid.";
Errors = new Dictionary<string, IEnumerable<string>>();
foreach (var item in modelState)
{
var itemErrors = new List<string>();
foreach (var childItem in item.Value.Errors)
{
itemErrors.Add(childItem.ErrorMessage);
}
Errors.Add(item.Key, itemErrors);
}
}
public string Message { get; set; }
public IDictionary<string, IEnumerable<string>> Errors { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后使用此错误类型而不是HttpError创建响应:
PrettyHttpError error = new PrettyHttpError(ModelState);
return Request.CreateResponse(HttpStatusCode.BadRequest, error);
Run Code Online (Sandbox Code Playgroud)
PrettyHttpError和PrefixlessBodyModelValidator的组合提供了您请求的输出.
| 归档时间: |
|
| 查看次数: |
4752 次 |
| 最近记录: |