在为这个问题苦苦挣扎了将近2天之后,我决定来到这里提出这个问题-我会尽我所能,做到尽可能清楚。

首先,我要做的事情很简单:实现一个自定义IValueProvider,该IValueProvider可以在ASP.NET MVC控制器内部解密操作的参数-这部分已经完成,并且运行良好。我的问题从动作参数中有一个列表的那一刻开始,因为我无法从请求上下文中精确确定此列表的值。

让我们逐步进行。

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

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为null,并且逻辑上为null,因为请求中没有该名称的键-我所拥有的只是一个这样的集合:

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


另一方面,我完全意识到我必须使用this.prefixContainer.Value.GetKeysFromPrefix(prefix);构造来获取请求中的所有键,并基于此,以某种方式联接这些键并将其返回给ValueProviderResult,但是没有想法! :-)

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

谢谢!

最佳答案

在过去几周针对这个问题进行了斗争之后,我决定我应该更改方法,并尝试不重新发明轮子。首先,我应该删除与收集处理有关的所有内容以及所有这些内容-因此有关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));


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

关于c# - 在自定义IValueProvider ASP.NET MVC 5.2.3中获取List <T>的值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36451610/

10-11 16:04