我已經創建了自定義ModelValidatorProvider,它應該僅在網站中的某些特定操作中處於活動狀態。 爲了做到這一點,我創建了一個自定義屬性,它擴展了「FilterAttribute」,並在OnAuthorize中設置了驗證器。ModelValidatorProviders基於頁面
在filter屬性中 - 爲了只在需要的頁面設置驗證器,我這樣做(PostAttributeModelValidatorProvider是驗證器提供者)。
var provider = (from p in ModelValidatorProviders.Providers
where p is PostAttributeModelValidatorProvider
select p).FirstOrDefault();
if (provider != null)
{
ModelValidatorProviders.Providers.Remove(provider);
}
if (EnableAttributesValidation)
{
ModelValidatorProviders.Providers.Add(new PostAttributeModelValidatorProvider() { BypassRequiredFieldsValidation = this.BypassRequiredFieldsValidation });
}
我面臨的問題是,有時(我無法檢測到什麼時候出了問題 - 但我認爲,當兩種用途嘗試訪問的網站或觸發這個動作的頁面時)還有就是我在做正因爲這樣的刪除和添加操作之間的衝突 - 我得到一個錯誤:
Index was outside the bounds of the array.
相關的堆棧跟蹤是:
[IndexOutOfRangeException: Index was outside the bounds of the array.] System.Collections.Generic.Enumerator.MoveNext() +112
System.Linq.d_711.MoveNext() +643
2.MoveNext() +578
System.Linq.<SelectManyIterator>d__14
System.Linq.d_142.MoveNext() +578
1 clientRules, IDictionary
System.Web.Mvc.UnobtrusiveValidationAttributesGenerator.GetValidationAttributes(IEnumerable2 results) +440
2 htmlAttributes) +1050
System.Web.Mvc.HtmlHelper.GetUnobtrusiveValidationAttributes(String name, ModelMetadata metadata) +280
System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, String format, IDictionary
System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper1 htmlHelper, Expression
1 expression, String format, IDictionary`2 htmlAttributes) +202 ASP._Page_Views_Home_Index_cshtml.Execute() in c:\interpub\wwwroot\Views\Home\Index.cshtml:47
共該屬性mplete源代碼是:
public class InitializePostAttributesResolverAttribute : FilterAttribute, IAuthorizationFilter
{
public InitializePostAttributesResolverAttribute()
: this(true, false)
{
}
public InitializePostAttributesResolverAttribute(bool enableAttributesValidation, bool bypassRequiredFieldsValidation)
{
this.EnableAttributesValidation = enableAttributesValidation;
this.BypassRequiredFieldsValidation = bypassRequiredFieldsValidation;
}
/// <summary>
/// Should the attributes input be validated
/// </summary>
public bool EnableAttributesValidation { get; set; }
/// <summary>
/// Gets or sets the value whether we should bypass the required fields validation
/// </summary>
/// <remarks>
/// This value should be set to true only if you would like to skip on required fields validation.
/// We should use this value when searching.
/// </remarks>
public bool BypassRequiredFieldsValidation { get; set; }
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ModelMetadataProviders.Current = new PostAttributeModelMetadataProvider();
var provider = (from p in ModelValidatorProviders.Providers
where p is PostAttributeModelValidatorProvider
select p).FirstOrDefault();
if (provider != null)
{
ModelValidatorProviders.Providers.Remove(provider);
}
if (EnableAttributesValidation)
{
ModelValidatorProviders.Providers.Add(new PostAttributeModelValidatorProvider() { BypassRequiredFieldsValidation = this.BypassRequiredFieldsValidation });
}
}
}
而且樣品使用它
//
// POST: /Post/Publish/5
[InitializePostAttributesResolver]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Publish(PublishViewModel model)
{
if (ModelState.IsValid)
{
// ...
}
}
難道我這樣做對嗎?我的目標(只是要明確)是僅在裝飾操作中啓用驗證程序提供程序,而在驗證程序提供程序集合中應該不存在其他操作。
謝謝!
沒有想到,謝謝! (雖然我仍然需要找出一種方法來添加「BypassRequiredFieldsValidation」屬性,該屬性在搜索時應該爲false,在添加/編輯時爲true),但我會考慮一種方式)。 – OzB
如果僅搜索,則可能會根據搜索詞從數據庫中填充模型,因此不會觸發驗證。驗證僅在您使用(默認)ModelBinder(發佈請求,或Controller方法UpdateModel(..)和TryUpdateModel(...))時觸發 – Nenad
是的我知道 - 我已經獲得由DB創建的自定義屬性與「FieldType」等)。驗證器提供程序驗證屬性(必需的,日期等)。在搜索中 - 我仍然需要執行驗證(例如「日期不大於X」或「0或更多」),但不希望要求值 - 因爲與添加或編輯記錄時不同 - 在搜索時,它們應該保持可選狀態並處於這種情況下,我不包括他們在搜索。 – OzB