【问题标题】:UrlHelper.Link returns undesired parametersUrlHelper.Link 返回不需要的参数
【发布时间】:2017-11-03 14:47:19
【问题描述】:

如果我在 API 调用中调用 UrlHelper.Link,该调用的参数与我试图为其获取 URL 的 API 端点的可选参数匹配,UrlHelper.Link 无论如何都会返回一个带有当前请求值的 URL我尝试从链接中排除可选参数。

例如

[HttpGet]
[Route("api/Test/Stuff/{id}")]
public async Task<IHttpActionResult> GetStuff(int id) // id = 78
{
    string link = Url.Link("Mary", new
    {
        first = "Hello",
        second = "World"
    });

    string link2 = Url.Link("Mary", new
    {
        first = "Hello",
        second = "World",
        id = (int?)null
    });

    string link3 = Url.Link("Mary", new
    {
        first = "Hello",
        second = "World",
        id = ""
    });

    return Ok(new
    {
        link,
        link2,
        link3
    });
}

[HttpGet]
[Route("api/Test/Another/{first}", Name = "Mary")]
public async Task<IHttpActionResult> AnotherMethod(
[FromUri]string first,
[FromUri]string second = null,
[FromUri]int? id = null)
{
    // Stuff
    return Ok();
}

获取http://localhost:53172/api/Test/Stuff/8

返回

{
  "link": "http://localhost:53172/api/Test/Another/Hello?second=World",
  "link2": "http://localhost:53172/api/Test/Another/Hello?second=World&id=8",
  "link3": "http://localhost:53172/api/Test/Another/Hello?second=World&id=8"
}

当 Url.Link 未呈现或分配给 null 或空字符串时,如何让 Url.Link 实际使用您传递给它的值,而不是从当前 api 请求中提取它?

我认为这个问题与 .... 非常相似。

UrlHelper.Action includes undesired additional parameters

但这是 Web API 而不是 MVC,不是一个动作,而且提供的答案似乎并没有为这个问题提供一个明显的解决方案。

编辑:我已经更新了代码,因为原始代码实际上并没有复制问题。我还包含了一个请求 URL 和返回的响应,我已经对其进行了测试。虽然这段代码演示了这个问题,但我试图找到修复的代码不是将匿名类型传递给 UrlHelper,而是它是一个生成时间戳和散列并具有 4 个可选参数的类。如果有另一个解决方案不需要省略传递给 UrlHelper 的结构中的可选参数,我想拥有它,因为它可以让我免于对代码进行大量更改。

【问题讨论】:

  • 同时显示原始网址和链接生成的网址。
  • 我建议答案更多的是解决方法。我认为这会引起很多人的注意,他们错误地认为将空值或 null 值分配给传递给 UrlHelper 的任何结构(包括匿名或类类型)上的属性与省略该值相同。虽然这种行为实际上可能是设计使然,但我认为这是非常错误的设想,而不是您所期望的

标签: .net asp.net-web-api owin


【解决方案1】:

传递路由值时不要包含id。事实上它不应该让你编译为

无法将&lt;null&gt; 分配给匿名类型属性

public async Task<IHttpActionResult> GetStuff(int id) // id = 78 {
    string myUrl = Url.Link(
        "Mary", 
        new 
        { 
            first = "Hello World"
        });

    //...other code
}

使用 web api 2 测试,id 在链接到其他操作时不包括在内。

[RoutePrefix("api/urlhelper")]
public class UrlHeplerController : ApiController {

    [HttpGet]
    [Route("")]
    public IHttpActionResult GetStuff(int id) {
        string myUrl = Url.Link(
            "Mary",
            new {
                first = "Hello World",
           });
        return Ok(myUrl);
    }

    [HttpGet]
    [Route(Name = "Mary")]
    public IHttpActionResult AnotherMethod(
    [FromUri]string first,
    [FromUri]string second = null,
    [FromUri]int? id = null) {
        // Stuff
        return Ok();
    }
}

打电话

client.GetAsync("/api/urlhelper?id=78")

路由到 GetStuff 操作并生成链接

"http://localhost/api/urlhelper?first=Hello%20World"

即使使用

进行测试
string myUrl = Url.Link(
    "Mary",
    new {
        first = "Hello World",
        id = ""
    });

id 未包含在生成的链接中。

【讨论】:

  • 我已经更新了问题。从技术上讲,这是我问题的答案。但是,与我提供的示例不同,我的实际代码不是将匿名类型传递给 UrlHelper,而是传递一个生成时间戳和散列并具有 4 个可选参数的类。根据您的回答,我需要创建该类的多个版本,一个用于所需的每种可能组合,公开操作所需的属性。
  • 我相信我的原始代码实际上并没有复制问题。我认为将 ID 作为 URL 的一部分包含在请求中而不是参数会改变行为
  • @Mick,那么你需要展示实际场景。在不是这种情况下显示匿名类型会产生误导。
  • 抱歉,如编辑中所述,在您回复后,我意识到原始代码并未完全复制该问题。我不相信传递一个类或匿名类型会有所作为,正如上面的代码所示,它在结构中存在属性。当您将包含设置为 null 或空字符串的属性的结构传递给 UrlHelper 时,会发生不希望的行为。显然,如果您使用匿名类型,则包含或省略特定属性要容易得多。
  • @Mick,它是否匿名很重要,因为框架使用提供的对象的所有属性来制作路由数据,即使您使用 null 或空填充它也是如此。因为一旦你省略了这个属性,问题就消失了。
猜你喜欢
  • 1970-01-01
  • 2019-05-27
  • 2015-06-20
  • 2016-04-24
  • 2010-10-17
  • 2019-08-03
  • 2021-06-18
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多