2

コントローラで次のアクションがあります。

[HttpGet]
public ActionResult Office(GestionOffice model)
{
    ModelState.Clear();
    model.Initialize();
    return View(model);
}

GETによるアクションは必要ありません。検証が行われます。これは、GETによる呼び出しのパフォーマンスに役立ちます。

これは私の理想的なケースです:

[HttpGet]
[NotValidateModel]
public ActionResult Office(GestionOffice model)
{
    model.Initialize();
    return View(model);
}

ありがとうございました。

編集

NotValidateModel存在しないことを明確にした場合、検証を回避するためにケースを帰属させます。

モデルを実際に移動する理由は、モデルに移動するためMOCKです

編集II

POSTを使用したアクションがあります。コントローラーでのアクションのテストを正常に完了するには、検証なしのモデルであるGETによってアクションを受け取る必要があります。

[HttpGet]
[NotValidateModel]
public ActionResult Office(GestionOffice model)
{
    model.Initialize();
    return View(model);
}

[HttpPost]
[ActionName("Office")]
[NotValidateModel]
public ActionResult OfficePost(GestionOffice model)
{
    if(ModelState.IsValid)
    {
        model.Save();
        return RedirectToAction("List");
    }

    model.Initialize();
    return View(model);
}

@Markのソリューションに関するエディション

私の見解では、アクションへの呼び出しがいくつかあるため、アクションとコントローラーを使用してキーを作成する必要がありました。

カスタムModelMetaData

public class CustomModelMetaData : ModelMetadata
{
    public CustomModelMetaData(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        : base(provider, containerType, modelAccessor, modelType, propertyName)
    {
    }

    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("NoValidation_{0}_{1}", controller, action);
    }
}

フィルター

public class NoValidationAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var itemKey = this.CreateKey(filterContext.ActionDescriptor);
        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("NoValidation_{0}_{1}", controller, action);
    }
}

フィルタを編集

メインビューにforeachがあり、属性を持つ複数の部分ビューを呼び出す場合がありますNoValidation。この場合、キーをチェックするためのコントロールが含まれています。キーにはコントローラーの名前とアクションが含まれているため、このキーはほぼ一意であり、説明されている場合にのみ繰り返すことができます。

public class NoValidationAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        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("NoValidation_{0}_{1}", controller, action);
    }
}
4

4 に答える 4

2

[質問の@ANDRESによって言及された編集も以下の更新を参照してください]

あなたがやろうとしていることを達成するのは少し難しいですし、なぜこれが基本的に必要なのかわかりません。私はカスタムModelMetaDataとフィルターを介して達成しようとしました(完全にはテストされていません)。

モデルバインダーまたはメタデータプロバイダーからのアクションで装飾された属性を読み取ることができないため、フィルターが必要です。フィルタはに値をHttpContext.Items設定し、カスタムメタデータプロバイダー(http://stackoverflow.com/questions/6198155/asp-net-mvc-modelbinder-getting-action-method)から値を取得できます。

フィルター

public class NoValidationAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
      // please see the edits in question to see the key generation
      filterContext.HttpContext.Items.Add("NoValidation", true);
    }
}

カスタムModelMetaData

public class CustomModelMetaData : ModelMetadata
{
    public CustomModelMetaData(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) :
      base(provider, containerType, modelAccessor, modelType, propertyName)
    {
    }

    public override System.Collections.Generic.IEnumerable<ModelValidator> GetValidators(ControllerContext context)
    {
      if (context.HttpContext.Items["NoValidation"] != null && bool.Parse(context.HttpContext.Items["NoValidation"].ToString()) == true)
        return Enumerable.Empty<ModelValidator>();

      return base.GetValidators(context);
    }
}

カスタムModelMetaDataProvider

public class CustomModelMetaDataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(System.Collections.Generic.IEnumerable<Attribute> attributes,
      Type containerType, Func<object> modelAccessor,
      Type modelType,
      string propertyName)
    {
      return new CustomModelMetaData(this, containerType, modelAccessor, modelType, 
         propertyName); 
    }
}

Global.asax.cs

ModelMetadataProviders.Current = new CustomModelMetaDataProvider();

使用法

[HttpGet]
[NoValidation]
public ActionResult Office(GestionOffice model)
{
   ...
}

=================================更新================ =====================

CustomModelMetaData継承して作成するのではなく、ModelMetadataから継承するのが良いと思いますDataAnnotationsModelMetadata

public class CustomModelMetaData : DataAnnotationsModelMetadata
{
    public CustomModelMetaData(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("NoValidation_{0}_{1}", controller, action);
    }
}

で、CustomModelMetaDataProviderいくつかのプロパティを設定する必要があります。

public class CustomModelMetaDataProvider : 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 CustomModelMetaData(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
      };
    }
}
于 2012-07-06T20:52:08.343 に答える
1

はい、次の[ValidateInput(false)]ような属性を使用します。

[ValidateInput(false)]
[HttpGet]
public ActionResult Office(GestionOffice model)
{
    model.Initialize();
    return View(model);
}
于 2012-07-06T18:40:56.497 に答える
0

Model.IsValid検証はPOSTで行われるため、削除して追加する必要があります[ValidateInput(false)]

[HttpPost]
[ValidateInput(false)]
[ActionName("Office")]
public ActionResult OfficePost(GestionOffice model)
{        
    model.Save();
    return RedirectToAction("List");
}

これで投稿は成功しますが、データベースに挿入する場合は注意が必要です。

于 2012-07-06T19:51:50.927 に答える
0

本番コードで検証なしで使用する場合は、サーバー側で無効になるため、クライアント側の検証を無効にする必要があります。

web.configを休閑地として変更します。

<appSettings>
    <add key="ClientValidationEnabled" value="false" />
</appSettings>
于 2012-07-06T19:30:19.517 に答える