【问题标题】:How to get the URL of the Action without parameters in ASP.NET MVC如何在 ASP.NET MVC 中获取不带参数的 Action 的 URL
【发布时间】:2016-11-20 10:28:42
【问题描述】:

我有一个在 IIS 上的虚拟目录中运行的 ASP.NET MVC Web 应用程序。 在应用程序中,我有一个 Action,它带有一个名为 Id 的参数。

public class MyController : MyBaseController 
{
    public ActionResult MyAction(int id)
    {
        return View(id);
    }
}

当我使用参数 123 调用 Action 时,生成的 URL 是这样的:

http://mywebsite.net/MyProject/MyController/MyAction/123

基本控制器中,如何优雅地找到不带任何参数的Action的URL?我想要得到的字符串是:/MyProject/MyController/MyAction

还有其他有关此问题的问题,但未涵盖这些情况。例如 Request.Url.GetLeftPart 仍然给我 ID。

【问题讨论】:

标签: c# asp.net asp.net-mvc url routes


【解决方案1】:

@trashr0x 的答案解决了问题的最大部分,但错过了MyProject 部分,并且不需要字典来构造所询问的字符串。这是一个简单的解决方案:

var result = string.Join("/", new []{ 
    Request.ApplicationPath, 
    RouteData.Values["controller"], 
    RouteData.Values["action"] 
});

【讨论】:

  • 谢谢。这给出了确切的结果。
  • 看来我也错过了MyProject 的要求。简单而优雅。
【解决方案2】:

您是否在默认路由中指定 id 设置为可选 (UrlParameter.Optional)?

routes.MapRoute(
    // route name
    "Default",
    // url with parameters
    "{controller}/{action}/{id}",
    // default parameters 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

更新 #1:以下是两种解决方案,一种适用于 id 是查询字符串 (?id={id}),另一种适用于 Uri (/{id}/) 的一部分:

var localPath = Request.Url.LocalPath;
// works with ?id=123
Debug.WriteLine("Request.Url.LocalPath: " + localPath);
// works with /123/
Debug.WriteLine("Remove with LastIndexOf: " + localPath.Remove(localPath.LastIndexOf('/') + 1));

更新 #2:好的,这是另一个尝试。它适用于所有场景(?id=?id=123//123/)并且我已将操作签名中的Id 更改为int? 而不是int(需要重构) :

var mvcUrlPartsDict = new Dictionary<string, string>();
var routeValues = HttpContext.Request.RequestContext.RouteData.Values;

if (routeValues.ContainsKey("controller"))
{
    if (!mvcUrlPartsDict.ContainsKey("controller"))
    {
        mvcUrlPartsDict.Add("controller", string.IsNullOrEmpty(routeValues["controller"].ToString()) ? string.Empty : routeValues["controller"].ToString());
    }
}

if (routeValues.ContainsKey("action"))
{
    if (!mvcUrlPartsDict.ContainsKey("action"))
    {
        mvcUrlPartsDict.Add("action", string.IsNullOrEmpty(routeValues["action"].ToString()) ? string.Empty : routeValues["action"].ToString());
    }
}

if (routeValues.ContainsKey("id"))
{
    if (!mvcUrlPartsDict.ContainsKey("id"))
    {
        mvcUrlPartsDict.Add("id", string.IsNullOrEmpty(routeValues["id"].ToString()) ? string.Empty : routeValues["id"].ToString());
    }
}

var uri = string.Format("/{0}/{1}/", mvcUrlPartsDict["controller"], mvcUrlPartsDict["action"]);
Debug.WriteLine(uri);

【讨论】:

  • 是的,参数id是可选的但是和这个有关系吗?
  • 在您的 OP 中添加您在示例中显示的操作的方法签名以及在代码中如何调用它们是一个好主意。
  • 在您的第二个解决方案中,如果省略 id 参数(因为它是可选的),则地址将为:/MyProject/MyController/。我会遗漏动作名称。
  • 更新了我的答案,看看吧。
【解决方案3】:

试试这个:

Request.Url.AbsoluteUri.Replace(Request.Url.Query, String.Empty);

但是如果没有查询字符串会报错

所以,你也可以直接试试:

Request.Url.AbsoluteUri

【讨论】:

【解决方案4】:

您是否尝试过以下方法:

string actionName = HttpContext.Request.RequestContext.RouteData.Values["Action"].ToString();
string controllerName = HttpContext.Request.RequestContext.RouteData.Values["Controller"].ToString();
var urlAction = Url.Action(actionName, controllerName, new { id = "" });

【讨论】:

  • urlAction 是“/MyProject/MyController/MyAction/123”
  • 你说得对,我没有意识到这一点。编辑了我的答案,现在应该可以了。
  • 现在,urlAction 是正确的,但这不适用于没有 id 作为参数的操作。由于我在基本控制器中使用此代码,因此代码将针对所有操作运行。
  • 除了 id 之外,您还向 Actions 传递了哪些其他参数?如果您传递其他参数,例如 Name,它应该作为 /MyProject/MyController/MyAction?Name=something 传递,在这种情况下,我的第一个解决方案将起作用。如果您不关心 MVC 操作的类似 REST 的 URL,只需从默认路由中删除“/{id}”,ID 应该作为 /MyController/MyAction?id=1 传递。你不会再有问题了。
  • 如果你不想放弃它并让你的默认路由保持原样,你只需要担心名为 id 的参数,它是唯一具有类似 REST 行为的参数网址。所有其他参数将作为?param1=x&param2=y 传递。因此,我的答案中的解决方案将起作用。如果您决定重写您的路由,以便所有参数以类似 REST 的方式传递:/MyProject/MyController/MyAction/123/param1Value/param2Value,那么您将无法为您的问题提供优雅的解决方案,因为您将始终取决于接收到的参数数量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
相关资源
最近更新 更多