首先要說明的問題真棒回答+ Daniel
不過,我已經把它做爲一個遠一點,完善它,並添加到它。
ValidationHander
我精這一點了。它現在基於一個通用的HttpOperationHandler
,因此它可以採用HttpRequestMessage
。這樣做的原因是我可以返回使用正確媒體類型格式化的錯誤消息(來自accept頭文件)。
public class ValidationHandler<TResource> : HttpOperationHandler<TResource, HttpRequestMessage, HttpRequestMessage>
{
public ValidationHandler() : base("response") { }
protected override HttpRequestMessage OnHandle(TResource model, HttpRequestMessage requestMessage)
{
var results = new List<ValidationResult>();
var context = new ValidationContext(model, null, null);
Validator.TryValidateObject(model, context, results, true);
if (results.Count == 0)
{
return requestMessage;
}
var errorMessages = results.Select(x => x.ErrorMessage).ToArray();
var mediaType = requestMessage.Headers.Accept.FirstOrDefault();
var response = new RestValidationFailure(errorMessages);
if (mediaType != null)
{
response.Content = new ObjectContent(typeof (string[]), errorMessages, mediaType);
}
throw new HttpResponseException(response);
}
}
擴展方法
您提供住宿幾乎從左右不再需要desc
放慢參數在ModelValidationFor
方法添加ValidationHandler時
我已經添加了相同的2額外的擴展方法。這是爲了確保所有「資源」類都經過驗證。這主要是我懶惰和健忘。我永遠忘記在某個地方添加一些類到列表中。 (這就是爲什麼我寫的通用溫莎安裝!)
public static void ValidateAllResourceTypes(this WebApiConfiguration config, string assemblyFilter = "MyCompany*.dll")
{
var path = Path.GetDirectoryName((new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
var dc = new DirectoryCatalog(path, assemblyFilter);
var assemblies = dc.LoadedFiles.Select(Assembly.LoadFrom).ToList();
assemblies.ForEach(assembly =>
{
var resourceTypes = assembly.GetTypes()
.Where(t => t.Namespace != null && t.Namespace.EndsWith("Resources"));
foreach (var resourceType in resourceTypes)
{
var configType = typeof(Extensions);
var mi = configType.GetMethod("ModelValidationFor");
var mi2 = mi.MakeGenericMethod(resourceType);
mi2.Invoke(null, new object[] { config });
}
});
}
我做了DirectoryCatalog
類使用System.ComponentModel.Composition.Hosting
命名空間(前身爲MEF)的。在這種情況下,我剛剛使用以「Resources」結尾的命名空間來查找我的「Resource」類。如果要將其更改爲使用自定義屬性或其他任何您可能更喜歡識別哪些類爲「資源」的方式,則不需要太多工作。
RestValidationFailure
這是一個小的輔助類我做了,允許驗證失敗的反應一致的行爲。
public class RestValidationFailure : HttpResponseMessage
{
public RestValidationFailure(string[] messages)
{
StatusCode = HttpStatusCode.BadRequest;
foreach (var errorMessage in messages)
{
Headers.Add("X-Validation-Error", errorMessage);
}
}
}
所以,現在我得到的所有驗證錯誤的一個很好的列表(在我的首選介質類型)。
享受! :)
優秀的答案! – Daniel