コントローラーとアクションの名前からUrisを作成するための情報はたくさんありますが、どうすればこれを逆に行うことができますか?
基本的に、私が達成しようとしているのは、参照ページ(つまりRequest.UrlReferrer)からコントローラーとアクションの名前を取得することです。これを達成する簡単な方法はありますか?
これでうまくいくと思う:
// 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"];
Visual Studioは現在ダウンしているため、テストできませんでしたが、期待どおりに動作するはずです。
Gdoronの答えを拡張するために、Uri
クラスには、文字列の解析を行わずにURLの左右の部分を取得するメソッドがあります。
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"];
Gdoranの受け入れられた答えに追加するために、カスタムルート属性が使用されている場合、アクションが設定されないことがわかりました。以下は私のために働く:
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";
}
@gordonのソリューションは機能しますが、使用する必要があります
return RedirectToAction(actionName.ToString(), controllerName.ToString(),values);
前のアクションに行きたい場合
応答オブジェクトを作成せずにこれを行う簡単な方法を次に示します。
var values = RouteDataContext.RouteValuesFromUri(Request.UrlReferrer);
var controllerName = values["controller"];
var actionName = values["action"];
このカスタムHttpContextBase
クラスを使用します
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;
}
}
RouteDataオブジェクトは次の情報にアクセスできます。
var controller = RouteData.Values["controller"].ToString();
var action = RouteData.Values["action"].ToString();
以前のController/Actionメソッド呼び出しを取得する組み込みの方法はないと思います。常にできることは、コントローラーとアクションメソッドをラップして永続的なデータストアに記録し、最後のコントローラー/アクションメソッドが必要な場合は、データベース(または選択したもの)から取得するだけです。
これは、URLにトークン(「))/」)が含まれているため、リファラーから簡略化されたURLを抽出するために作成したメソッドです。これにより、コントローラーとアクションを簡単に抽出できます。
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;
}
なぜURLからActionLinkを構築する必要があるのですか? ActionLinkの目的は、一部のデータからURLを作成することとは正反対です。だからあなたのページで:
var fullUrl = Request.UrlReferrer.ToString();
<a href="@fullUrl">Back</a>