我有有,我用它来筛选我的数据很多属性筛选器属性视图模型
例:
class MyViewModel : IHasFilter
{
public MyData[] Data { get; set; }
public FilterViewModel Filter { get; set; }
}
class FilterViewModel
{
public String MessageFilter { get; set; }
//etc.
}
用我查看时,这工作得很好。 我可以设置的属性Model.Filter
和它们传递给控制器。 我试图现在要做的,是创造一个ActionLink
,有一个查询字符串与上述格式的作品。
从上面我查看生成的查询字符串看起来是这样的:
http://localhost:51050/?Filter.MessageFilter=Stuff&Filter.OtherProp=MoreStuff
我需要生成一个不同的视图用于在云上面的查看网格每一行ActionLink的。
我努力了:
Html.ActionLink(
item.Message,
"Index",
"Home",
new { Filter = new { MessageFilter = item.Message, }, },
null);
我也试过设置routeValues
参数:
new MyViewModel { Filter = new FilterViewModel { MessageFilter = item.Message, }, },
但这些不生成查询字符串像上面一个。
你可以从一个创建RouteValueDictionary FilterViewModel
实例,然后使用ToDictionary
上传递到与前缀的所有键另一RouteValues 'Filter.'
。
把它进一步,你可以建立一个特殊的覆盖RouteValueDictionary
它接受一个前缀(因此使其成为其他方案的更多有用的):
public class PrefixedRouteValueDictionary : RouteValueDictionary
{
public PrefixedRouteValueDictionary(string prefix, object o)
: this(prefix, new RouteValueDictionary(o))
{ }
public PrefixedRouteValueDictionary(string prefix, IDictionary<string, object> d)
: base(d.ToDictionary(kvp=>(prefix ?? "") + kvp.Key, kvp => kvp.Value))
{ }
}
这样,您现在就可以这样做:
Html.ActionLink(
item.Message,
"Index",
"Home",
new PrefixedRouteValueDictionary("Filter.",
new FilterViewModel() { MessageFilter = item.Message }),
null);
需要说明的这一点,不过,是的Add
, Remove
, TryGetValue
与this[string key]
方法不改变,以顾及prefix
。 这可以通过定义来实现new
的这些方法的版本,而是因为他们不是虚拟的,他们会只从知道他们在说一个呼叫者工作PrefixedRouteValueDictionary
而不是RouteValueDictionary
。
有趣的问题(+1)。 我假设的目的是使用默认的模型绑定到查询字符串参数绑定到你的Action
参数。
开箱即用的,我不相信ActionLink
方法会为你做这个(当然没有什么滚动自己阻止你)。 展望反射器我们可以看到,当object
被添加到RouteValueDictionary
,只添加键值对。 这是添加键值对的代码,你可以看到有没有穿越的对象属性。
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
{
object obj2 = descriptor.GetValue(values);
this.Add(descriptor.Name, obj2);
}
因此,对于您的对象
var values = new { Filter = new Filter { MessageFilter = item.Message } }
所添加的关键是Filter
和值是您的Filter
对象,将评估你的对象类型的完全限定名。
这样做的结果是Filter=Youre.Namespace.Filter
。
根据您的实际需要 修改 可能的解决方案
扩展方法 做的工作
需要注意的是它采用了静态的框架方法ExpressionHelper
和ModelMetadata
(也使用现有的助手),以确定相应的名称,默认模式粘结剂将分别了解和财产的价值。
public static class ExtentionMethods
{
public static MvcHtmlString ActionLink<TModel, TProperty>(
this HtmlHelper<TModel> helper,
string linkText,
string actionName,
string controllerName,
params Expression<Func<TModel, TProperty>>[] expressions)
{
var urlHelper = new UrlHelper(helper.ViewContext.HttpContext.Request.RequestContext);
var url = urlHelper.Action(actionName, controllerName);
if (expressions.Any())
{
url += "?";
foreach (var expression in expressions)
{
var result = ExpressionHelper.GetExpressionText(expression);
var metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, helper.ViewData);
url = string.Concat(url, result, "=", metadata.SimpleDisplayText, "&");
}
url = url.TrimEnd('&');
}
return new MvcHtmlString(string.Format("<a href='{0}'>{1}</a>", url, linkText));
}
}
样本模型
public class MyViewModel
{
public string SomeProperty { get; set; }
public FilterViewModel Filter { get; set; }
}
public class FilterViewModel
{
public string MessageFilter { get; set; }
}
行动
public ActionResult YourAction(MyViewModel model)
{
return this.View(
new MyViewModel
{
SomeProperty = "property value",
Filter = new FilterViewModel
{
MessageFilter = "stuff"
}
});
}
用法
任何数量的您的视图模型的属性可以通过最后被添加到查询字符串params
方法的参数。
@this.Html.ActionLink(
"Your Link Text",
"YourAction",
"YourController",
x => x.SomeProperty,
x => x.Filter.MessageFilter)
标记
<a href='/YourAction/YourController?SomeProperty=some property value&Filter.MessageFilter=stuff'>Your Link Text</a>
而不是使用string.Format
你可以使用TagBuilder
,查询字符串应该被编码为在URL中安全地过去了,这个扩展方法将需要一些额外的验证,但我认为这可能是有用的。 还需要注意的是,虽然这个扩展方法是专为MVC 4,它可以很容易地修改了以前的版本。 我没有意识到的是,MVC标签的那一次是为3版本到现在为止。