How do I get the Controller and Action names from

2019-01-11 17:05发布

问题:

There's a lot of information for building Uris from Controller and Action names, but how can I do this the other way around?

Basically, all I'm trying to achieve is to get the Controller and Action names from the referring page (i.e. Request.UrlReferrer). Is there an easy way to achieve this?

回答1:

I think this should do the trick:

// 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"];

My Visual Studio is currently down so I could not test it, but it should work as expected.



回答2:

To expand on gdoron's answer, the Uri class has methods for grabbing the left and right parts of the URL without having to do string parsing:

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"];


回答3:

The RouteData object can access this info:

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


回答4:

To add to gdoran's accepted answer, I found that the action doesn't get populated if a custom route attribute is used. The following works for 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";
}


回答5:

@gordon's solution works, but you need to use

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

if you want to go to previous action



回答6:

I don't believe there is any built-in way to retrieve the previous Controller/Action method call. What you could always do is wrap the controllers and action methods so that they are recorded in a persistent data store, and then when you require the last Controller/Action method, just retrieve it from the database (or whatever you so choose).



回答7:

This is a method I made to extract url simplified from referrer because I had token (finished with "))/") in my URL so you can extract easily controller and action from this:

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;
    }


回答8:

Why would you need to construct ActionLink from a url ? The purpose of ActionLink is just the opposite to make a url from some data. So in your page just do:

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


回答9:

Here is a lightweight way to do this without creating response objects.

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

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

Uses this custom HttpContextBase class

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;
    }
}