获取自定义IValueProvider ASP.NET MVC 5.2.3中的List <t>的值

时间:2016-04-06 12:46:19

标签: c# asp.net asp.net-mvc asp.net-mvc-4

在这个问题上挣扎了将近两天之后,我决定来这里问这个问题 - 我会尽我所能尽力而为。

首先,我要做的是非常简单:实现一个自定义的IValueProvider来解密ASP.NET MVC控制器中的一个动作的参数 - 这部分已经完成并且它工作正常;我的问题始于我在动作参数中有一个List,因为我无法从请求上下文中确定此列表的值。

让我们一步一步来。

首先,我有一个属性来装饰所需的操作:

public class EncryptedQueryStringValuesAttribute : FilterAttribute, IAuthorizationFilter
{
    /// <summary>
    /// Called when authorization is required.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        filterContext.Controller.ValueProvider = new EncryptedQueryStringValuesProvider(
            filterContext.RequestContext, filterContext.ActionDescriptor);
    }
}

接下来,我有值提供者构造函数,我正在初始化我需要的东西:

public EncryptedQueryStringValuesProvider(RequestContext requestContext, ActionDescriptor actionDescriptor)
{
    this.requestContext = requestContext;
    this.actionDescriptor = actionDescriptor;

    this.prefixContainer =
        new Lazy<PrefixContainer>(
            () => new PrefixContainer(this.requestContext.HttpContext.Request.Params.AllKeys), true);
}

作为旁注,prefixContainer它真的像魅力一样工作 - 如果我正在检查容器中是否有前缀,它无论前缀类型如何都能正常工作(这意味着参数是否无关紧要)集合或简单参数)。

检查值提供程序中是否存在参数是这样的:

public bool ContainsPrefix(string prefix)
{
    return this.prefixContainer.Value.ContainsPrefix(prefix);
}

正如我所说 - 这给了我正确的价值。

现在,丑陋的部分 - GetValue方法:

public ValueProviderResult GetValue(string key)
{
    string[] rawValue = this.requestContext.HttpContext.Request.Params.GetValues(key);
    string attemptedValue = this.requestContext.HttpContext.Request.Params[key];
    return new ValueProviderResult(rawValue, attemptedValue, CultureInfo.CurrentCulture);
}

现在提取的rawValue为空,并且逻辑为空,因为我的请求中没有该名称的密钥 - 我所拥有的只是一个这样的集合:

[25]: "SupplierInvoices[x].PaymentToInvoiceExchangeRate"
[26]: "SupplierInvoices[x].AmountToPayOnGivenInvoice"
[27]: "SupplierInvoices[x].OpenInvoiceId"
[28]: "SupplierInvoices[x].OpenInvoiceTimestamp"

另一方面,我完全清楚我必须使用this.prefixContainer.Value.GetKeysFromPrefix(prefix);构造来获取我的请求中的所有密钥并基于此,以某种方式加入这些密钥并将它们返回给ValueProviderResult,但没有想法如何! : - )

请有人可以解释如何将这些值连接起来,以便传递回ValueProviderResult以便正确解释?

谢谢!

1 个答案:

答案 0 :(得分:1)

在最近几周与这个问题作斗争之后,我决定改变方法并尝试不重新发明轮子。首先,我应该删除与收集处理相关的所有内容以及所有这些内容 - 所以关于this.prefixContainer的所有内容都应该去 - 如果我在HTTPContext中找不到简单的密钥,我就不应该处理它并将其留给其他提供者。

这是另一个问题 - 如何“告诉”我的价值提供者“关注”关键词?最初我认为如果我在ContainsPrefix方法中返回false,处理将切换到队列中的下一个IValueProvider - 事实并非如此 - ContainsPrefix方法都应该返回null更重要的是,GetValue方法应该返回null,并且只有在这些情况下,处理才会移到下一个IValueProvider

好的 - 现在我已经完成了所有这些工作,如何在没有全局注册ValueProviderFactory的情况下使用我的价值提供者,因为正如我所说,处理仅针对“已签名”的行为进行具有给定属性。答案是这样的 - 而不是使用如下属性代码在ValueProvider中实例化自定义Controller

filterContext.Controller.ValueProvider = new EncryptedQueryStringValuesProvider(filterContext.RequestContext, filterContext.ActionDescriptor);

我必须将我的价值提供者添加到列表顶部:

ValueProviderCollection valueProviderCollection = filterContext.Controller.ValueProvider as ValueProviderCollection;
if (valueProviderCollection == null)
throw new NullReferenceException("filterContext.Controller.ValueProvider as ValueProviderCollection");

valueProviderCollection.Insert(0, new EncryptedQueryStringValuesProvider(filterContext.RequestContext, filterContext.ActionDescriptor));

我希望这会对某人有所帮助。 : - )