在为这个问题苦苦挣扎了将近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/