Interessante Frage (+1). Ich nehme an, dass der Zweck darin besteht, den Standard-Modellbinder zu verwenden, um die Querystring-Parameter an Ihre Action
Parameter zu binden.
Out of the box Ich glaube nicht, dass die ActionLink
Methode dies für Sie tun wird (natürlich gibt es nichts, was Sie daran hindert, Ihre eigenen zu rollen). Wenn wir im Reflektor suchen, können wir sehen, dass, wenn die object
zu RouteValueDictionary
hinzugefügt wird, nur Schlüsselwertpaare hinzugefügt werden. Dies ist der Code, der die Schlüsselwertpaare hinzufügt, und wie Sie sehen können, werden die Objekteigenschaften nicht durchsucht.
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
{
object obj2 = descriptor.GetValue(values);
this.Add(descriptor.Name, obj2);
}
So für Ihr Objekt
var values = new { Filter = new Filter { MessageFilter = item.Message } }
der Schlüssel hinzugefügt wird, ist Filter
und der Wert ist Ihr Filter
Objekt, das mit dem vollständig qualifizierten Namen des Objekttypen auswerten wird.
Das Ergebnis ist Filter=Youre.Namespace.Filter
.
bearbeitenmögliche Lösung auf Ihre genauen Bedürfnisse je
Erweiterungsmethodemacht die Arbeit
Beachten Sie, dass es die statischen Rahmen Methoden verwendet ExpressionHelper
und ModelMetadata
(die werden auch von den vorhandenen Helfern verwendet), um die passenden Namen zu ermitteln, die der Standard-Modellbinder wird verstehen und Wert der Eigenschaft jeweils.
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));
}
}
Beispielmodelle
public class MyViewModel
{
public string SomeProperty { get; set; }
public FilterViewModel Filter { get; set; }
}
public class FilterViewModel
{
public string MessageFilter { get; set; }
}
Aktion
public ActionResult YourAction(MyViewModel model)
{
return this.View(
new MyViewModel
{
SomeProperty = "property value",
Filter = new FilterViewModel
{
MessageFilter = "stuff"
}
});
}
Nutzungs
Eine beliebige Anzahl von Ansichtsmodelleigenschaften kann über den letzten params
Parameter der Methode zum Querystring hinzugefügt werden.
@this.Html.ActionLink(
"Your Link Text",
"YourAction",
"YourController",
x => x.SomeProperty,
x => x.Filter.MessageFilter)
Markup
<a href='/YourAction/YourController?SomeProperty=some property value&Filter.MessageFilter=stuff'>Your Link Text</a>
Statt string.Format
verwenden Sie TagBuilder
verwenden könnte, sollte die Abfragezeichenfolgeflag codiert werden sicher in einer URL übergeben werden und diese Erweiterung Methode würde eine zusätzliche Validierung müssen aber Ich denke, es könnte nützlich sein. Beachten Sie auch, dass diese Erweiterungsmethode zwar für MVC 4 erstellt wurde, jedoch leicht für frühere Versionen geändert werden kann. Ich wusste nicht, dass das eine der MVC-Tags bis jetzt für Version 3 war.
+1 eine gute Frage –
danke für den Schnitt; Ich habe die Antwort refaktoriert und im Ersatz vergessen, das 'Präfix' hinzuzufügen! –
@AndrasZoltan Keine Probleme. – DaveShaw