3

I am new to MVC, and trying to navigate via js to a controller action method. The code works (as in the action method is hit), but the parameter value I am passing in is always null

js:

  window.location.href = "@Url.Action("Step1", "Reports")" + "/?" + rsid;

Controller action:

public class ReportsController : Controller    {

     public ActionResult Step1(int? rsid)
        {

          //do stuff
        }
}

The rsid parameter is always null. I have tried various link formats, eg "/?rsid=[id]", "/[id]"

Do I need a custom route for the parameter to be picked up?

Or maybe annotate the action method with [httpPost] or [httpGet]?

Polynomial Proton
  • 5,020
  • 20
  • 37
Programnik
  • 1,449
  • 1
  • 9
  • 13

5 Answers5

2

The easiest way to do it is to just name the parameter "id" since it is in the default route and call from js like this:

'@Html.ActionLink("Step1", "Reports", new { id = ' + rsid + ' })'

public ActionResult Step1(int? id)
{

          //do stuff
}
Nikola Davidovic
  • 8,556
  • 1
  • 27
  • 33
  • In my case parameter value (for example rsid here) are encode with javaScript encodeURIComponent() so in MVC Action return parameter has null value, I don't know why! – QMaster Apr 20 '18 at 12:14
2

No need for string concatenation. It's bug prone, as you've discovered. Simply provide an anonymous object with your route values (using a different overload of UrlHelper.Action) and let MVC routing decide how to represent it all.

To make this fail-safe, you'll also need to make sure your URL is safe to store in a JavaScript string by wrapping it in a call to HttpUtility.JavaScriptStringEncode, then rendered without HTML encoding by wrapping in Html.Raw:

window.location.href = 
 "@Html.Raw(HttpUtility.JavaScriptStringEncode(Url.Action("Step1", "Reports", new{rsid})))";

You could simplify matters with a helper extension method (an extension on HtmlHelper seems convenient to me)

public static class JavascriptHelperEx
{
    public static IHtmlString QuotedJsString(this HtmlHelper htmlHelper, string str)
    {
        //true parameter below wraps everything in double quotes:
        return htmlHelper.Raw(HttpUtility.JavaScriptStringEncode(str, true));
    }
}

So now:

window.location.href = @Html.QuotedJsString(Url.Action("Step1", "Reports", new{rsid}));
spender
  • 117,338
  • 33
  • 229
  • 351
  • 1
    Yes, also still need `@Html.Raw(...` as `@` will HtmlEncode the url. `location.href` *may* handle such over-encoded url, but regular url manipulation in JavaScript will likely be completely confused (not directly applicable to OP's case)... – Alexei Levenkov Apr 16 '15 at 01:00
  • Yes... One option is to wrap it in helper code that will return `HtmlString` to avoid `Html.Raw` (combining answers from [here](http://stackoverflow.com/questions/8300605/how-to-encode-embedded-javascript-in-razor-view-in-asp-net-mvc-3) for example... ). I know there are couple good answers with versions I like, can't find them now. – Alexei Levenkov Apr 16 '15 at 01:06
  • @AlexeiLevenkov: Thx for your contributions – spender Apr 16 '15 at 01:16
2

You probably mapping to a default route which is: /controller/action/id. Now in your action declaration you named your parameter as rsid which will not map to id because name is different. Change your action signature to:

public ActionResult Step1(int? id)

or option b) is specify the name of your parameter from js side:

window.location.href = "@Url.Action("Step1", "Reports")" + "/?rsid=" + rsid;
Marko
  • 12,543
  • 10
  • 48
  • 58
0

What URL does this create?

"@Url.Action("Step1", "Reports")" + "/?" + rsid;

Something like this:

http://server/controller/action/?123

There's no parameter in that URL called rsid, so the model binder doesn't know where to find that value. You need to give the value a key:

"@Url.Action("Step1", "Reports")" + "/?rsid=" + rsid;

This would create something more like this:

http://server/controller/action/?rsid=123
David
  • 208,112
  • 36
  • 198
  • 279
  • Thanks David, I think I discovered the issue, if I rename my controller param to id and get rid of the question mark in the url it works because it matches a default routing pattern. So does that mean if I want to have meaningful parameter names (rather than just id) in controller actions I need to have a custom route mask for each param pattern? (or just extract the param values from the query string old-school) – Programnik Apr 16 '15 at 00:59
0

try to have a rsid after the ? so the value will map to rsid

window.location.href = "@Url.Action("Step1", "Reports")" + "/?rsid=" + rsidValue;
jmvtrinidad
  • 3,347
  • 3
  • 22
  • 42