gpt4 book ai didi

.net - 如何从 ModelState 键中删除前缀?

转载 作者:行者123 更新时间:2023-12-03 11:34:50 28 4
gpt4 key购买 nike

例如,有一个 Web Api 操作方法:

public HttpMessageResponse Post(UserDto userDto)
{
if (!this.ModelState.IsValid)
{
return this.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, this.ModelState);
}

// ...
}

客户端发送以下请求:
HTTP POST: /api/user
{ "username": "me", "password": "Pa$sw0rd" }

并得到响应:
HTTP 201/Created:
{ "message": "Your request is invalid.",
"modelState": { "userDto.Password": "Your password is too strong." } }

默认情况下,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");
}

// ...
}

最佳答案

对于第一部分:

Also error messages returned to a client shouldn't contain those prefixes



我同意将参数名称作为所有模型状态错误的前缀并不是很好的行为。幸运的是,具有此行为的服务是可替换的。您只需要有一个自定义的 IbodyModelValidator。下面是它的样子(使用装饰器模式让默认服务完成大部分工作):
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);
}
}

然后,用您的服务包装默认服务:
config.Services.Replace(typeof(IBodyModelValidator), new PrefixlessBodyModelValidator(config.Services.GetBodyModelValidator()));

对于第二部分:

elso replace "modelState" with "errors"



它目前说“modelState”的原因是您当前的代码:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);

正在有效地执行以下操作:
HttpError error = new HttpError(ModelState, false);
return Request.CreateResponse(HttpStatusCode.BadRequest, error);

由于 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; }
}

然后使用此错误类型而不是 HttpError 创建响应:
PrettyHttpError error = new PrettyHttpError(ModelState);
return Request.CreateResponse(HttpStatusCode.BadRequest, error);

PrettyHttpError 和 PrefixlessBodyModelValidator 的组合提供了您请求的输出。

关于.net - 如何从 ModelState 键中删除前缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17106151/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com