Перелив и Билал, спасибо за ответ на мой вопрос.
@Bilal: Я использую ту же модель для сохранения и отправки и не хочу никаких атрибутов на модели, а нуждаюсь в чем-то на уровне контроллера/действия.
В поиске, чтобы найти лучший ответ, я придумал что-то вроде этого. Я прочитал это из другой статьи, но потерял ссылку. Как только я получу его, я обновлю то же самое.
Добавить новый атрибут действия фильтра
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class IgnoreValidationAttribute : FilterAttribute, IAuthorizationFilter
{
// TODO: Try to put it on another more appropriate method such as OnActionExcecuting.
// Looks like - This is the earliest method we can interpret before an action. I really dont like this!
public void OnAuthorization(AuthorizationContext filterContext)
{
//TODO: filterContext != null && filterContext.httpContext != null
var itemKey = this.CreateKey(filterContext.ActionDescriptor);
if (!filterContext.HttpContext.Items.Contains(itemKey))
{
filterContext.HttpContext.Items.Add(itemKey, true);
}
}
private string CreateKey(ActionDescriptor actionDescriptor)
{
var action = actionDescriptor.ActionName.ToLower();
var controller = actionDescriptor.ControllerDescriptor.ControllerName.ToLower();
return string.Format("IgnoreValidation_{0}_{1}", controller, action);
}
}
Override DataAnnotationModelMetadata
public class IgnoreValidationModelMetaData : DataAnnotationsModelMetadata
{
public IgnoreValidationModelMetaData(DataAnnotationsModelMetadataProvider provider, Type containerType,
Func<object> modelAccessor, Type modelType, string propertyName,
DisplayColumnAttribute displayColumnAttribute) :
base(provider, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute)
{
}
public override IEnumerable<ModelValidator> GetValidators(ControllerContext context)
{
var itemKey = this.CreateKey(context.RouteData);
if (context.HttpContext.Items[itemKey] != null && bool.Parse(context.HttpContext.Items[itemKey].ToString()) == true)
{
return Enumerable.Empty<ModelValidator>();
}
return base.GetValidators(context);
}
private string CreateKey(RouteData routeData)
{
var action = (routeData.Values["action"] ?? null).ToString().ToLower();
var controller = (routeData.Values["controller"] ?? null).ToString().ToLower();
return string.Format("IgnoreValidation_{0}_{1}", controller, action);
}
}
Теперь скажите поставщику использовать наши метаданные аннотаций пользовательских данных и опустошить проверки, если IgnoreValidationAttribute является присутствующих в методе действия
public class IgnoreValidationModelMetaDataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var displayColumnAttribute = new List<Attribute>(attributes).OfType<DisplayColumnAttribute>().FirstOrDefault();
var baseMetaData = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
// is there any other good strategy to copy the properties?
return new IgnoreValidationModelMetaData(this, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute)
{
TemplateHint = baseMetaData.TemplateHint,
HideSurroundingHtml = baseMetaData.HideSurroundingHtml,
DataTypeName = baseMetaData.DataTypeName,
IsReadOnly = baseMetaData.IsReadOnly,
NullDisplayText = baseMetaData.NullDisplayText,
DisplayFormatString = baseMetaData.DisplayFormatString,
ConvertEmptyStringToNull = baseMetaData.ConvertEmptyStringToNull,
EditFormatString = baseMetaData.EditFormatString,
ShowForDisplay = baseMetaData.ShowForDisplay,
ShowForEdit = baseMetaData.ShowForEdit,
Description = baseMetaData.Description,
ShortDisplayName = baseMetaData.ShortDisplayName,
Watermark = baseMetaData.Watermark,
Order = baseMetaData.Order,
DisplayName = baseMetaData.DisplayName,
IsRequired = baseMetaData.IsRequired
};
}
}
Использование
[HttpPost]
[IgnoreValidation]
public ActionResult SaveDraft(MyModel myModel)
{
if (ModelState.IsValid)
{
// Should always reach here
}
.......
}
[HttpPost]
public ActionResult Submit(MyModel myModel)
{
if (ModelState.IsValid)
{
}
}
Пожалуйста, не забудьте назвать это в вашей Application_Start для wireup «ModelMetadataProviders.Current = новый IgnoreValidationModelMetaDataProvider();
Есть несколько проблем, хотя.
Есть ли раннее место, где мы могли бы манипулировать HttpContext, чем OnAuthorization()?. Мне не нравится идея переопределить это, чтобы сделать что-то, не связанное с авторизацией. Обратите внимание, что OnActionExecuting() будет слишком поздно в конвейере MVC для этого (я пробовал это и не работал).
Есть ли лучший способ сделать это, чем добавить ключ к HttpContext и использовать его позже?
Пожалуйста, не забудьте называть это в своем приложении Application_Start для проводника 'ModelMetadataProviders.Current = new IgnoreValidationModelMetaDataProvider();' –