1

我正在构建一个 NopCommerce 插件,并希望在与其他方法共享 ActionName 的 ActionMethod 上使用 FilterProvider 注册自定义 ActionFilter。

这是两个具有相同 ActionName 的 ActionMethods

[HttpPost, ActionName("Edit")]
[FormValueRequired("cancelorder")]      
public ActionResult CancelOrder(int id)
{...}

[HttpPost, ActionName("Edit")]
[FormValueRequired("captureorder")]      
public ActionResult CaptureOrder(int id)
{...}

在我的过滤器提供程序中,我需要以某种方式将 CancelOrder 方法与 CaptureOrder 分开:

public class OrderFilterProvider : IFilterProvider
{
    private readonly IActionFilter _actionFilter;

    public OrderFilterProvider(IActionFilter actionFilter)
    {
        _actionFilter = actionFilter;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {       
        if (actionDescriptor.ControllerDescriptor.ControllerType == typeof(OrderController) &&
            actionDescriptor.ActionName.Equals("Edit"))
        {
            return new Filter[] 
            { 
                new Filter(_actionFilter, FilterScope.Action, null)
            };
        }

        return new Filter[] { };
    }
}

使用此代码,过滤器在 CancelOrder 和 CaptureOrder 上都注册了,如何仅在 CancelOrder 方法上注册它?

我的想法是根据方法名称或 FormValueRequired 属性中的参数值将它们分开,但没有运气找到这样做的方法。

FormValueRequired 没有任何公共属性,如下所示:

public class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
private readonly string[] _submitButtonNames;
private readonly FormValueRequirement _requirement;

public FormValueRequiredAttribute(params string[] submitButtonNames):
    this(FormValueRequirement.Equal, submitButtonNames)
{
}

public FormValueRequiredAttribute(FormValueRequirement requirement, params string[] submitButtonNames)
{
    //at least one submit button should be found
    this._submitButtonNames = submitButtonNames;
    this._requirement = requirement;
}
}

这是我的调试器中的样子:http ://www.tiikoni.com/tis/view/?id=4843369

有没有办法获取方法的名称?

4

3 回答 3

2

我可以看到这两个动作之间的唯一区别是存在一些自定义FormValueRequired属性,不幸的是你没有显示也没有解释它的作用,但我猜它是一些动作选择器。无论如何,您可以检索此属性:

public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
    if (actionDescriptor.ControllerDescriptor.ControllerType == typeof(OrderController) &&
        actionDescriptor.ActionName.Equals("Edit"))
    {
        // Get the FormValueRequiredAttribute that was used to decorate the action
        var formValueRequiredAttribute = actionDescriptor
            .GetCustomAttributes(typeof(FormValueRequiredAttribute), false)
            .Cast<FormValueRequiredAttribute>()
            .FirstOrDefault();

        // if the action was decorated with this attribute we could read the
        // property that was passed to the constructor (hopefully it is exposed
        // as a public property)
        if (formValueRequiredAttribute != null && 
            formValueRequiredAttribute.SomeParameter == "captureorder")
        {
            // The CaptureOrder action was invoked
            return new Filter[] 
            { 
                new Filter(_actionFilter, FilterScope.Action, null)
            };
        }
    }

    return new Filter[] { };
}
于 2013-02-24T09:17:40.143 回答
1

FormValueRequired 属性实际上检查发布数据的“名称”。因此,如果您的 POST 表单有一个名称为“cancelorder”的名称-值对,则将执行 Action 方法。(有趣的是,FormValueRequired 检查名称-值对的“名称”,但不检查名称-值对的“值”)。

换句话说,保留您的 ActionFilter,并让两个 Action 触发 ActionFilter。但是在您实际的 ActionFilter 方法中,检查 POSTed 表单是否具有适当的名称,代码如下:

controllerContext.HttpContext.Request.Form["cancelorder"];

您可以在 OnXXX ActionFilter 方法参数中轻松获取 ControllerContext。:)

于 2013-03-05T16:51:23.280 回答
0

需要注意的一件重要事情:即使 FormValueRequired 属性只检查发布数据的“名称”,您仍然需要为其提供一个值才能工作。

例如,这将不起作用:

<input type="submit" name="continueshopping" value="" class="continue-shopping-button" />

我想要一个没有文本值的按钮,所以我必须为值输入一个空格,如下所示:

<input type="submit" name="continueshopping" value=" " class="continue-shopping-button" />
于 2013-10-17T13:53:46.390 回答