Search code examples
asp.net-mvcasp.net-mvc-routingasp.net-core-2.2

.net core 2.2 call action using taghelpers and passing querystring


I have a simple search action in Controller A. I know its not the most efficient, but it seems to work.

[HttpPost, ActionName("Search")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Search(string cellnumberFragment, string clientFragment, string serviceFragment, string deviceFragment, string networkFragment, string serialFragment)
{
    var thirdPartySims = _context.ThirdPartySim.AsQueryable();

    if (!string.IsNullOrWhiteSpace(cellnumberFragment)) thirdPartySims = thirdPartySims.Where(s => s.Cellnumber.Contains(cellnumberFragment));
    if (!string.IsNullOrWhiteSpace(clientFragment)) thirdPartySims = thirdPartySims.Where(s => s.Client.Name.Contains(clientFragment));
    if (!string.IsNullOrWhiteSpace(serviceFragment)) thirdPartySims = thirdPartySims.Where(s => s.Service.Name.Contains(serviceFragment));
    if (!string.IsNullOrWhiteSpace(deviceFragment)) thirdPartySims = thirdPartySims.Where(s => s.DeviceName.Contains(deviceFragment));
    if (!string.IsNullOrWhiteSpace(networkFragment)) thirdPartySims = thirdPartySims.Where(s => s.Network.Name.Contains(networkFragment));
    if (!string.IsNullOrWhiteSpace(serialFragment)) thirdPartySims = thirdPartySims.Where(s => s.Serial.Contains(serialFragment));

    return View(await thirdPartySims.ToListAsync());
}

In a View for Controller B, I want to have a link to the search conntroller, passing specified values to the Search behind the scenes. The dictionary allows me to cleanly specify each action param. It's then added with the tag helper asp-all-route-data

@{
    var parms = new Dictionary<string, string>
    {
        {"cellnumberFragment", null },
        {"clientFragment", Model.Name },
        {"serviceFragment", null },
        {"deviceFragment", null },
        {"networkFragment", null },
        {"serialFragment", null }
    };
}
<a asp-controller="ThirdPartySims" asp-action="Search" asp-all-route-data="parms">List all SIM's for client</a>

This is creating a link like

http://localhost:52827/ThirdPartySims/Search?clientFragment=Not%20Specified

When I load the Search normally, via the Index view, it works fine. When run this way, via a link using tag-handlers, I get

This page isn’t working If the problem continues, contact the site owner.
HTTP ERROR 405

And my vs2019 log says

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: 
Request starting HTTP/1.1 GET 
http://localhost:52827/ThirdPartySims/Search  
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: 
Executing endpoint '405 HTTP Method Not Supported'
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: 
Executed endpoint '405 HTTP Method Not Supported'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: 
Request finished in 6.3539ms 405 

Solution

  • Looks like a get, post related issue.

    "When I load the Search normally, via the Index view"

    I guess you have a search form with default post method, so this is a post request, and since you do have a post search method [HttpPost] it works fine.

    "When run this way, via a link using tag-handlers, I get..."

    Actually the issue is not the tag helpers, but using links means it is a get request and that's why you are getting an error.

    Solution 1:

    If you need to access the search functionality via links, just mark the method as get HttpGet and remove antiforgery token validation, so you will be able to use links with search params included in the url.

    [HttpGet, ActionName("Search")]
    public async Task<IActionResult> Search([FromQuery] string cellnumberFragment, string clientFragment, string serviceFragment, string deviceFragment, string networkFragment, string serialFragment)
    {
        var thirdPartySims = _context.ThirdPartySim.AsQueryable();
    
        if (!string.IsNullOrWhiteSpace(cellnumberFragment)) thirdPartySims = thirdPartySims.Where(s => s.Cellnumber.Contains(cellnumberFragment));
        if (!string.IsNullOrWhiteSpace(clientFragment)) thirdPartySims = thirdPartySims.Where(s => s.Client.Name.Contains(clientFragment));
        if (!string.IsNullOrWhiteSpace(serviceFragment)) thirdPartySims = thirdPartySims.Where(s => s.Service.Name.Contains(serviceFragment));
        if (!string.IsNullOrWhiteSpace(deviceFragment)) thirdPartySims = thirdPartySims.Where(s => s.DeviceName.Contains(deviceFragment));
        if (!string.IsNullOrWhiteSpace(networkFragment)) thirdPartySims = thirdPartySims.Where(s => s.Network.Name.Contains(networkFragment));
        if (!string.IsNullOrWhiteSpace(serialFragment)) thirdPartySims = thirdPartySims.Where(s => s.Serial.Contains(serialFragment));
    
        return View(await thirdPartySims.ToListAsync());
    }
    

    Solution 2:

    just make a post request to the search function, if you still need to use a link you may see this answer https://stackoverflow.com/a/33880971/5519026