LinkGenerator returns NULL Url while Url.Action doesn't ... Why
Asked Answered
S

2

6

On an ASP.NET Core 2.2 Controller I tried to generate a Link in 3 ways:

var a = Url.Action(action: "GetContentByFileId", values: new { fileId = 1 });

var b = _linkGenerator.GetUriByAction(HttpContext, action: "GetContentByFileId", controller: "FileController", values: new { fileId = 1 });

var c = _linkGenerator.GetUriByAction(_httpContextAccessor.HttpContext, action: "GetContentByFileId", controller: "FileController", values: new { fileId = 1 });

Result

  • In "a", using Url.Action I get the right link ...

  • In "b" and "c" I get null and I am providing the same data ... I think.

I am injecting LinkGenerator in the Controller and it is not null ...

I am also injecting HttpContextAccessor and I have on Startup:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

FileController is:

[ApiVersion("1.0", Deprecated = false), Route("v{apiVersion}")]
public class FileController : Controller {

  private readonly IHttpContextAccessor _httpContextAccessor;
  private readonly LinkGenerator _linkGenerator; 

  public FileController(IHttpContextAccessor httpContextAccessor, LinkGenerator linkGenerator) {

    _httpContextAccessor = httpContextAccessor;
    _linkGenerator = linkGenerator;

  }

  [HttpGet("files/{fileId:int:min(1)}")]
  public async Task<IActionResult> GetContentByFileId(FileGetModel.Request request) {
    // Remaining code
  }

What am I missing?

Update

I was able to pin point the problem besides Controller suffix as answered by TanvirArjel.

All urls are correct if I comment the following code line:

[ApiVersion("1.0", Deprecated = false), Route("v{apiVersion}")]

But if I add the previous code line and the following on Startup:

services.AddApiVersioning(x => {
  x.ApiVersionSelector = new CurrentImplementationApiVersionSelector(x);
  x.AssumeDefaultVersionWhenUnspecified = true;
  x.DefaultApiVersion = new ApiVersion(1, 0);
  x.ReportApiVersions = false;
});

Then the urls become null ...

What this ApiVersion is adding is "v1.0" before files so it becomes "v1.0/files".

So the linkGenerator should become:

var b = _linkGenerator.GetUriByAction(HttpContext, 
  action: "GetContentByFileId", 
  controller: "File", 
  values: new { apiVersion = "1.0", fileId = 1 
});

Question

Is there a way to integrate apiVersion in LinkGenerator without specifying it?

Salleysalli answered 22/1, 2019 at 10:16 Comment(0)
D
9

Problem is that you are using Controller Name with Controller suffix. Please remove Controller suffix from the controller name and write as follows:

var b = _linkGenerator.GetUriByAction(HttpContext, 
    action: "GetContentByFileId", 
    controller: "File", 
    values: new { FileId = 1 }
);

Now it should work.

Diocletian answered 22/1, 2019 at 11:43 Comment(6)
This looks interesting.Burnet
No it doesn't solve it ... I already tried but I tried just now once more. "b" is null again. And "a" using Url.Action is not.Salleysalli
I am already using it! and checked it again.It works perfectly.Diocletian
@MiguelMoura I have also checked that it returns null only when ControllerName is mentioned with Controller suffix or action name is not found. So please check your code again in both for b and cDiocletian
@Diocletian I tried your code and it wasn't the only problem ... I just updated the question. I now know how to solve it ... Not sure if there is a better way to do it ... any suggestion?Salleysalli
Does this mean we're stuck using hardcoded strings for the Controller instead of being able to use nameof()?Ostracize
F
0
         app.UseEndpoints(endpoints =>
          {
            // Default route
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Account}/{action=Login}/{id?}");
           });

services.AddMvc(options => options.EnableEndpointRouting = true);

      string url = _generator.GetUriByAction("index", "home", null, 
 _accessor.HttpContext.Request.Scheme, _accessor.HttpContext.Request.Host);
        var url1 = _generator.GetPathByAction("index", "home", 
   new { FileId = 1 });
Flex answered 22/9, 2020 at 5:29 Comment(1)
Replace the default MVC route in your application to UseEndpoints route in configure method in startup.cs .Flex

© 2022 - 2024 — McMap. All rights reserved.