Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 操作包括不需要的附加参数_C#_Asp.net Mvc 4_Urlhelper - Fatal编程技术网

C# 操作包括不需要的附加参数

C# 操作包括不需要的附加参数,c#,asp.net-mvc-4,urlhelper,C#,Asp.net Mvc 4,Urlhelper,我在controllerapplicationcontroller中有一个方法,其中我需要获取操作方法的基本URL: public ActionResult MyAction(string id) { var url = Url.Action("MyAction", "Applications"); ... } 问题在于,当我需要不带URL的URL时,这包括来自当前路由数据的字符串id(URL用于在基于URL的查找中从CMS获取内容) 我已尝试将null和new{}作为rout

我在controller
applicationcontroller
中有一个方法,其中我需要获取操作方法的基本URL:

public ActionResult MyAction(string id)
{
    var url = Url.Action("MyAction", "Applications");
    ...
}
问题在于,当我需要不带URL的URL时,这包括来自当前路由数据的
字符串id
(URL用于在基于URL的查找中从CMS获取内容)

我已尝试将
null
new{}
作为
routeValues
参数传递,但均无效

匹配路线如下(高于所有其他路线):

我已经看到一些其他问题涉及到这一点,但似乎没有一个可行的解决方案。目前,我在控制器中对路径进行硬编码;但是,我希望能够将其抽象为一个操作过滤器,因此我需要能够生成URL


是否有一种干净/常规的方法来防止这种行为?

使用
id
的空值来防止
Url。操作
使用当前的方法:

var url = Url.Action("MyAction", "Applications", new { id = "" })

好的,我明白问题所在了。这就是所谓的“段变量重用”。当为出站URL生成路由,并尝试在路由的URL模式中查找每个段变量的值时,路由系统将查看来自当前请求的值。这是一种使许多程序员感到困惑的行为,并可能导致冗长的调试会话。路由系统热衷于与路由进行匹配,以便重用来自传入URL的段变量值。所以我认为你必须像Julien建议的那样覆盖这个值:

var url = Url.Action("MyAction", "Applications", new { id = "" })

最终用不同的方法解决了这个问题。我能想出的防止将任意命名的路由值插入生成的URL的唯一方法是在调用
URL.Action
时将它们从
RouteData
中临时删除。我已经编写了一些扩展方法来促进这一点:

public static string NonContextualAction(this UrlHelper helper, string action)
{
    return helper.NonContextualAction(action,
        helper.RequestContext.RouteData.Values["controller"].ToString());
}

public static string NonContextualAction(this UrlHelper helper, string action,
                                         string controller)
{
    var routeValues = helper.RequestContext.RouteData.Values;
    var routeValueKeys = routeValues.Keys.Where(o => o != "controller"
                         && o != "action").ToList();

    // Temporarily remove routevalues
    var oldRouteValues = new Dictionary<string, object>();
    foreach (var key in routeValueKeys)
    {
        oldRouteValues[key] = routeValues[key];
        routeValues.Remove(key);
    }

    // Generate URL
    string url = helper.Action(routeValues["Action"].ToString(),
                               routeValues["Controller"].ToString());

    // Reinsert routevalues
    foreach (var kvp in oldRouteValues)
    {
        routeValues.Add(kvp.Key, kvp.Value);
    }

    return url;
}
公共静态字符串非文本操作(此UrlHelper,字符串操作)
{
返回帮助程序。非文本化(操作,
helper.RequestContext.routedData.Values[“controller”].ToString());
}
公共静态字符串非文本化(此UrlHelper、字符串操作、,
字符串控制器)
{
var routeValues=helper.RequestContext.RouteData.Values;
var routeValueKeys=routeValues.Keys.Where(o=>o!=“控制器”
&&o!=“动作”).ToList();
//暂时删除RouteValue
var oldRouteValues=新字典();
foreach(routeValueKeys中的var键)
{
oldRouteValues[键]=routeValues[键];
路由值。移除(键);
}
//生成URL
字符串url=helper.Action(routeValue[“Action”].ToString(),
routeValue[“Controller”].ToString());
//重新插入RouteValue
foreach(旧路由值中的var kvp)
{
RouteValue.Add(kvp.Key,kvp.Value);
}
返回url;
}
这允许我在操作过滤器中执行此操作,在该过滤器中,我不一定知道操作的参数名称(因此不能像其他答案那样只传递匿名对象)


不过,我仍然很想知道是否有人有更优雅的解决方案。

我对@AntP的其他优秀解决方案中的
路由数据的改变、暂时的或其他的方式并不完全满意。由于我创建链接的代码已经集中化,我借用了@Tomasz Jaskuλa和@AntP来扩充
ExpandoObject
,我已经使用了

IDictionary<string,object> p = new ExpandoObject();

// Add the values I want in the route
foreach (var (key, value) in linkAttribute.ParamMap)
{
    var v = GetPropertyValue(origin, value);                    
    p.Add(key, v); 
}

// Ideas borrowed from https://stackoverflow.com/questions/20349681/urlhelper-action-includes-undesired-additional-parameters
// Null out values that I don't want, but are already in the RouteData
foreach (var key in _urlHelper.ActionContext.RouteData.Values.Keys)
{
    if (p.ContainsKey(key))
        continue;

    p.Add(key, null); 
}

var href = _urlHelper.Action("Get", linkAttribute.HRefControllerName, p);
IDictionary p=new ExpandoObject();
//在管线中添加所需的值
foreach(linkAttribute.ParamMap中的var(键,值)
{
var v=GetPropertyValue(原点,值);
p、 添加(键,v);
}
//借鉴https://stackoverflow.com/questions/20349681/urlhelper-action-includes-undesired-additional-parameters
//清除我不需要的值,但这些值已经在RouteData中
foreach(在_urlHelper.ActionContext.RouteData.Values.Keys中的var键)
{
如果(p.CONTANSKEY(关键))
继续;
p、 Add(key,null);
}
var href=_urlHelper.Action(“Get”,linkAttribute.HRefControllerName,p);

您确定此路由正在解决此问题吗?(如果它是唯一的)。@ThomasJaskula-肯定-我有一个直接在它下面的catchall路由,直接重定向到静态CMS内容。注释应用程序路由输出会导致第二条路由捕获它。将其作为第一个调用端口进行测试,这是唯一一条针对该URL进行解析的路由。将对此进行一次尝试,但是否有任何方法可以在不显式指定单个参数名称的情况下强制执行此操作?我想将其抽象为一个动作过滤器,其中URL段不一定总是被称为idI。我不认为有一种简单的方法可以做到这一点,因为它被烘焙到MVC框架中。这需要自定义路由系统。这种行为总是让我大吃一惊,这就是为什么我认为路由是MVC最糟糕的部分。这种情况不应该经常发生,我正在逐案处理。我是通过UrlHelper.Link获得这种行为的,但这并不能解决所有好方法的问题。事实上,Url类本身应该有一个替代这些行为的选项(比如Action方法上的可选bool参数)。@MarceloMyara这也是我的想法——事实上,我很惊讶没有考虑到这一点。
IDictionary<string,object> p = new ExpandoObject();

// Add the values I want in the route
foreach (var (key, value) in linkAttribute.ParamMap)
{
    var v = GetPropertyValue(origin, value);                    
    p.Add(key, v); 
}

// Ideas borrowed from https://stackoverflow.com/questions/20349681/urlhelper-action-includes-undesired-additional-parameters
// Null out values that I don't want, but are already in the RouteData
foreach (var key in _urlHelper.ActionContext.RouteData.Values.Keys)
{
    if (p.ContainsKey(key))
        continue;

    p.Add(key, null); 
}

var href = _urlHelper.Action("Get", linkAttribute.HRefControllerName, p);