2012-01-12 8 views
28

Ci sono molte informazioni per costruire Uris dai nomi di Controller e Action, ma come posso farlo al contrario?Come si ottengono i nomi del controller e dell'azione dall'URI del referrer?

Fondamentalmente, tutto quello che sto cercando di ottenere è ottenere i nomi di controller e di azioni dalla pagina di riferimento (cioè Request.UrlReferrer). C'è un modo semplice per raggiungere questo obiettivo?

+1

http://stackoverflow.com/questions/7087663/getting-the-names-of-previous-action-and-controller-in-mvc- controller – Maheep

risposta

45

Penso che questo dovrebbe fare il trucco:

// Split the url to url + query string 
var fullUrl = Request.UrlReferrer.ToString(); 
var questionMarkIndex = fullUrl.IndexOf('?'); 
string queryString = null; 
string url = fullUrl; 
if (questionMarkIndex != -1) // There is a QueryString 
{  
    url = fullUrl.Substring(0, questionMarkIndex); 
    queryString = fullUrl.Substring(questionMarkIndex + 1); 
} 

// Arranges 
var request = new HttpRequest(null, url, queryString); 
var response = new HttpResponse(new StringWriter()); 
var httpContext = new HttpContext(request, response) 

var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); 

// Extract the data  
var values = routeData.Values; 
var controllerName = values["controller"]; 
var actionName = values["action"]; 
var areaName = values["area"]; 

mio Visual Studio è attualmente giù così non ho potuto provarlo, ma dovrebbe funzionare come previsto.

+2

Si potrebbe voler modificare questo codice un po '. Se il tuo referrer non ha una querystring, finirai per provare a chiamare fullUrl.Substring (0, -1). – rossisdead

+1

@rossisdead. fatto. grazie per il consiglio. – gdoron

+0

Per quanto mi riguarda, non sono riuscito a ottenere il nome dell'area nel modo in cui descrivi da "routeData.Values", invece ho usato "routeData.DataTokens [" area "]'. – Leigh

3

L'oggetto RouteData può accedere a queste informazioni:

var controller = RouteData.Values["controller"].ToString(); 
var action = RouteData.Values["action"].ToString(); 
+24

Ciò fornirà i dati correnti, non i dati precedenti. – gdoron

+0

http://stackoverflow.com/a/31749391/4293929 – MstfAsan

0

Non credo ci sia un modo integrato per recuperare la precedente chiamata al metodo Controller/Azione. Quello che potresti sempre fare è racchiudere i controller ei metodi di azione in modo che vengano registrati in un archivio dati persistente, e quindi quando hai bisogno dell'ultimo metodo Controller/Azione, basta recuperarlo dal database (o qualsiasi altra cosa tu scelga).

0

questo è un metodo che ho fatto per estrarre url semplificata dal referrer perché ho avuto per memoria (finito con ")) /") nel mio URL in modo da poter estrarre facilmente controllore e l'azione da questa:

private static string GetURLSimplified(string url) 
    { 
     string separator = "))/"; 
     string callerURL = ""; 

     if (url.Length > 3) 
     { 
      int index = url.IndexOf(separator); 
      callerURL = url.Substring(index + separator.Length); 
     } 
     return callerURL; 
    } 
0

Perché dovresti costruire ActionLink da un URL? Lo scopo di ActionLink è esattamente l'opposto di creare un URL da alcuni dati. Quindi, nella tua pagina basta fare:

var fullUrl = Request.UrlReferrer.ToString(); 
<a href="@fullUrl">Back</a> 
2

Per aggiungere al di gdoran risposta accettato, ho scoperto che l'azione non viene popolata se si utilizza un attributo percorso personalizzato. Le seguenti opere per me:

public static void SetUpReferrerRouteVariables(HttpRequestBase httpRequestBase, ref string previousAreaName, ref string previousControllerName, ref string previousActionName) 
{ 
    // No referrer found, perhaps page accessed directly, just return. 
    if (httpRequestBase.UrlReferrer == null) return; 

    // Split the url to url + QueryString. 
    var fullUrl = httpRequestBase.UrlReferrer.ToString(); 
    var questionMarkIndex = fullUrl.IndexOf('?'); 
    string queryString = null; 
    var url = fullUrl; 
    if (questionMarkIndex != -1) // There is a QueryString 
    { 
     url = fullUrl.Substring(0, questionMarkIndex); 
     queryString = fullUrl.Substring(questionMarkIndex + 1); 
    } 

    // Arrange. 
    var request = new HttpRequest(null, url, queryString); 
    var response = new HttpResponse(new StringWriter()); 
    var httpContext = new HttpContext(request, response); 

    var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); 
    if (routeData == null) throw new AuthenticationRedirectToReferrerDataNotFoundException(); 

    // Extract the data. 
    var previousValues = routeData.Values; 
    previousAreaName = previousValues["area"] == null ? string.Empty : previousValues["area"].ToString(); 
    previousControllerName = previousValues["controller"] == null ? string.Empty : previousValues["controller"].ToString(); 
    previousActionName = previousValues["action"] == null ? string.Empty : previousValues["action"].ToString(); 
    if (previousActionName != string.Empty) return; 
    var routeDataAsListFromMsDirectRouteMatches = (List<RouteData>)previousValues["MS_DirectRouteMatches"]; 
    var routeValueDictionaryFromMsDirectRouteMatches = routeDataAsListFromMsDirectRouteMatches.FirstOrDefault(); 
    if (routeValueDictionaryFromMsDirectRouteMatches == null) return; 
    previousActionName = routeValueDictionaryFromMsDirectRouteMatches.Values["action"].ToString(); 
    if (previousActionName == "") previousActionName = "Index"; 
} 
1

@ soluzione di Gordon funziona, ma è necessario utilizzare

return RedirectToAction(actionName.ToString(), controllerName.ToString(),values); 

se si vuole passare all'azione precedente

2

Ad ampliare la risposta di gdoron, il Uri la classe ha metodi per afferrare le parti sinistra e destra dell'URL senza dover eseguire l'analisi delle stringhe:

url = Request.UrlReferrer.GetLeftPart(UriPartial.Path); 
querystring = Request.UrlReferrer.Query.Length > 0 ? uri.Query.Substring(1) : string.Empty; 

// Arranges 
var request = new HttpRequest(null, url, queryString); 
var response = new HttpResponse(new StringWriter()); 
var httpContext = new HttpContext(request, response) 

var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); 

// Extract the data  
var values = routeData.Values; 
var controllerName = values["controller"]; 
var actionName = values["action"]; 
var areaName = values["area"]; 
+1

usa 'querystring = Request.UrlReferre.GetComponents (UriComponents.Query, UriFormat.UriEscaped);' invece per la querystring. –

0

So che questo post è vecchio ma ho pensato che fosse bello.

Se avete un'idea su come il percorso è configurato si potrebbe fare:

Dim reffererPaths As String() = Request.UrlReferrer.Segments 

ho usato per determinare se dovessi caricare un layout o no:

Function YourAction() As ActionResult 
     Dim refererPaths As String() = Request.UrlReferrer.Segments 
     Dim controller As String = RouteData.Values("controller").ToString() 

     If refererPaths(2).Replace("/", "") <> controller Then 
      Return View("YourAction", "SpecificLayout") 
     End If 

     Return View() 
    End Function 

Per me, refererPaths (2) sarebbe sempre stato il mio controller. Se c'è stata un'azione specificata dopo il controller, ho appena rimosso il "/" dal segmento e quindi ho confrontato il controller del referrer con il controller corrente.

0

Ecco un modo leggero per eseguire questa operazione senza creare oggetti risposta.

var values = RouteDataContext.RouteValuesFromUri(Request.UrlReferrer); 

var controllerName = values["controller"]; 
var actionName = values["action"]; 

utilizza questa personalizzato HttpContextBase classe

public class RouteDataContext : HttpContextBase { 
    public override HttpRequestBase Request { get; } 

    private RouteDataContext(Uri uri) { 
     var url = uri.GetLeftPart(UriPartial.Path); 
     var qs = uri.GetComponents(UriComponents.Query,UriFormat.UriEscaped); 

     Request = new HttpRequestWrapper(new HttpRequest(null,url,qs)); 
    } 

    public static RouteValueDictionary RouteValuesFromUri(Uri uri) { 
     return RouteTable.Routes.GetRouteData(new RouteDataContext(uri)).Values; 
    } 
} 
Problemi correlati