在这个问题上挣扎了将近两天之后,我决定来这里问这个问题 - 我会尽我所能尽力而为。
首先,我要做的是非常简单:实现一个自定义的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以便正确解释?
谢谢!
答案 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));
我希望这会对某人有所帮助。 : - )