c# - mvc - html.actionlink parameters
MVC ActionLink agrega todos los parĂ¡metros(opcionales) de la url actual (5)
El famoso ActionLink
:
<%: Html.ActionLink("Back to List", "Index")%>
Ahora, este enlace está en mi vista de detalles. La vista de índice es una página de búsqueda. La URL de que se ve así:
http://localhost:50152/2011-2012/Instelling/Details/76?gemeente=Dendermonde&postcode=92**&gebruikerscode=VVKSO114421&dossiernr=114421%20&organisatie=CLB
Como puedes ver, bastante la cantidad de parámetros. Obviamente, quiero mantener todos estos parámetros cuando regrese a la página Índice, por lo que necesito agregarlos en el ActionLink
.
Ahora, estoy cansado de hacerlo manualmente, está bien para 1, pero no para 6. Esto debería ser mucho más fácil.
Pregunta: ¿Cómo devuelvo todos los parámetros de la URL actual a ActionLink
como RouteValues
opcional RouteValues
He estado buscando en Request.QueryString
. Tiene que ser algo con eso. Estaba pensando en escribir algún método estático en Global.asax
haciendo el trabajo, pero aún no he tenido suerte. Tal vez hay una manera fácil de hacer esto que no conozco?
Editar: Esto es lo que se me ocurrió (que funciona)
En global.asax:
public static RouteValueDictionary optionalParamters(NameValueCollection c) {
RouteValueDictionary r = new RouteValueDictionary();
foreach (string s in c.AllKeys) {
r.Add(s, c[s]);
}
return r;
}
Details.aspx:
<%: Html.ActionLink("Back to List", "Index", MVC2_NASTEST.MvcApplication.optionalParamters(Request.QueryString))%>
¿Dónde pongo mejor este código? no en Global.asax
, supongo ...
Edición 2:
using System;
using System.Web.Mvc;
namespace MVC2_NASTEST.Helpers {
public static class ActionLinkwParamsExtensions {
public static MvcHtmlString CustomLink(this HtmlHelper helper, string linktext) {
//here u can use helper to get View context and then routvalue dictionary
var routevals = helper.ViewContext.RouteData.Values;
//here u can do whatever u want with route values
return null;
}
}
}
<%@ Import Namespace="MVC2_NASTEST.Helpers" %>
...
<%: Html.ActionLinkwParams("Index") %>
Aquí hay un método de extensión para ViewContext que crea un RouteValueDictionary basado en los valores de la ruta de solicitud y la cadena de consulta.
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
namespace MyMvcApplication.Utilities
{
public static class ViewContextExtensions
{
/// <summary>
/// Builds a RouteValueDictionary that combines the request route values, the querystring parameters,
/// and the passed newRouteValues. Values from newRouteValues override request route values and querystring
/// parameters having the same key.
/// </summary>
public static RouteValueDictionary GetCombinedRouteValues(this ViewContext viewContext, object newRouteValues)
{
RouteValueDictionary combinedRouteValues = new RouteValueDictionary(viewContext.RouteData.Values);
NameValueCollection queryString = viewContext.RequestContext.HttpContext.Request.QueryString;
foreach (string key in queryString.AllKeys.Where(key => key != null))
combinedRouteValues[key] = queryString[key];
if (newRouteValues != null)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(newRouteValues))
combinedRouteValues[descriptor.Name] = descriptor.GetValue(newRouteValues);
}
return combinedRouteValues;
}
}
}
Puede pasar el RouteValueDictionary creado a Html.ActionLink o Url.Action
@Html.ActionLink("5", "Index", "Product",
ViewContext.GetCombinedRouteValues(new { Page = 5 }),
new Dictionary<string, object> { { "class", "page-link" } })
Si el parámetro Página no existe en la URL de solicitud, se agregará en la URL generada. Si existe, su valor será cambiado a 5.
Este artículo tiene una explicación más detallada de mi solución.
Así es como finalmente lo arreglé, y estoy bastante orgulloso porque está funcionando muy bien y muy SECO.
La llamada en la vista:
<%: Html.ActionLinkwParams("Back to List", "Index")%>
pero con las sobrecargas puede ser cualquier cosa que tome un ActionLink normal.
El ayudante
El ayudante toma todos los parámetros de la url que no están en la ruta. Por ejemplo: esta url:
http://localhost:50152/2011-2012/myController/Details/77?postalCode=9***&org=CLB
Así que tomará el código postal y la organización y lo colocará en el nuevo ActionLink. Con la sobrecarga, se pueden agregar parámetros adicionales y los parámetros de la URL existente se pueden eliminar.
using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace MVC2_NASTEST.Helpers {
public static class ActionLinkwParamsExtensions {
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs, object htmlAttributes) {
NameValueCollection c = helper.ViewContext.RequestContext.HttpContext.Request.QueryString;
RouteValueDictionary r = new RouteValueDictionary();
foreach (string s in c.AllKeys) {
r.Add(s, c[s]);
}
RouteValueDictionary htmlAtts = new RouteValueDictionary(htmlAttributes);
RouteValueDictionary extra = new RouteValueDictionary(extraRVs);
RouteValueDictionary m = Merge(r, extra);
return System.Web.Mvc.Html.LinkExtensions.ActionLink(helper, linktext, action, controller, m, htmlAtts);
}
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action) {
return ActionLinkwParams(helper, linktext, action, null, null, null);
}
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller) {
return ActionLinkwParams(helper, linktext, action, controller, null, null);
}
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs) {
return ActionLinkwParams(helper, linktext, action, null, extraRVs, null);
}
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, string controller, object extraRVs) {
return ActionLinkwParams(helper, linktext, action, controller, extraRVs, null);
}
public static MvcHtmlString ActionLinkwParams(this HtmlHelper helper, string linktext, string action, object extraRVs, object htmlAttributes) {
return ActionLinkwParams(helper, linktext, action, null, extraRVs, htmlAttributes);
}
static RouteValueDictionary Merge(this RouteValueDictionary original, RouteValueDictionary @new) {
// Create a new dictionary containing implicit and auto-generated values
RouteValueDictionary merged = new RouteValueDictionary(original);
foreach (var f in @new) {
if (merged.ContainsKey(f.Key)) {
merged[f.Key] = f.Value;
} else {
merged.Add(f.Key, f.Value);
}
}
return merged;
}
}
}
En la vista usando sobrecargas:
<%: Html.ActionLinkwParams("Back to List", "Index","myController", new {testValue = "This is a test", postalCode=String.Empty}, new{ @class="test"})%>
En la URL tengo los parámetros postalCode con algún valor. mi código los toma a todos en la URL, al establecerlos en string.Empty, elimino este parámetro de la lista.
Los comentarios o ideas son bienvenidos para optimizarlo.
Cree un método de extensión ToRouteValueDictionary () para que Request.QueryString use Html.ActionLink tal como está y simplifique el marcado de su vista:
<%: Html.ActionLink("Back to List", "Index", Request.QueryString.ToRouteValueDictionary())%>
Su método de extensión podría verse así:
using System.Web.Routing;
using System.Collections.Specialized;
namespace MyProject.Extensions
{
public static class CollectionExtensions
{
public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection collection)
{
var routeValueDictionary = new RouteValueDictionary();
foreach (var key in collection.AllKeys)
{
routeValueDictionary.Add(key, collection[key]);
}
return routeValueDictionary;
}
}
}
Para usar el método de extensión en su vista, vea esta pregunta y respuesta: ¿Cómo uso un método de extensión en una vista de ASP.NET MVC?
Esto es más simple e implica mucho menos código que la respuesta aceptada.
Quizás la mejor manera es escribir su propio ayudante html donde recorre el diccionario de valor de ruta anterior y agregue los valores de ruta al enlace de acción actual, excepto el parámetro de acción fuera de curso.
Edición: Puedes escribir el ayudante html así:
public static MvcHtmlString CustomLink(this HtmlHelper helper,string linktext)
{
//here you can use helper to get View context and then routvalue dictionary
var routevals = helper.ViewContext.RouteData.Values;
//here you can do whatever you want with route values
}
public static class Helpers
{
public static MvcHtmlString CustomLink(this HtmlHelper helper,string LinkText, string actionName)
{
var rtvals = helper.ViewContext.RouteData.Values;
var rtvals2 = helper.RouteCollection;
RouteValueDictionary rv = new RouteValueDictionary();
foreach (string param in helper.ViewContext.RequestContext.HttpContext.Request.QueryString.AllKeys)
{
rv.Add(param, helper.ViewContext.RequestContext.HttpContext.Request.QueryString[param]);
}
foreach (var k in helper.ViewContext.RouteData.Values)
{
rv.Add(k.Key, k.Value);
}
return helper.ActionLink(LinkText, actionName, rv);
}
}
He probado esto y su funcionamiento. Se pueden adquirir parámetros opcionales de la cadena de consulta HTH