Value cannot be null. Parameter name: String in asp.net mvc C# - asp.net-mvc

I am pretty new to asp.net mvc. I want to get the parameter string in my url
http://localhost/Item/ItemSpec/3431?dep=62&cat=129&tab=2
How can I get the value=3431?
I tried to used HttpContext.Current.Request.QueryString["id"], but it's not work. 3431 is the id of the item that display in my page, that's why I used ["id"].
Thanks you so much.

The 3431 is part of the path of the request, not part of the query string. You could use HttpRequest.Path to get at the path, but MVC routing should allow you to simply write a controller method which accepts the ID as a parameter. I suggest you read up on how to configure routing. (Just searching for ASP.NET routing or MVC routing will give you lots of articles.)

Assuming the default route is configured in Global.asax ({controller}/{action}/{id}) you could have your controller action take an id parameter and the default model binder will automatically set its value:
public ActionResult Foo(string id)
{
...
}
If you want to fetch this id value from some other portion of your code that does have access to an HttpContext you need to fetch it from the RouteData:
var id = HttpContext.Request.RequestContext.RouteData["id"];
RouteData is available in all standard MVC locations. In your example you have used the static HttpContext.Current property which is something that you should never use. I suspect that you are trying to fetch this id from a portion of your code where you are not supposed to have access to the HttpContext. So you'd better fetch this id using standard techniques and then pass it as parameter to other parts of your code.

If Item is your controller, and ItemSpec is action, you can get the Id just by
public ActionResult ItemSpec(int id) { }
You routing have to be setup to:
context.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index" }
);

If you haven't changed your routing so it's still defined as it was when you created Asp.net MVC Web project then this should be one of your controllers:
public class ItemController : ControllerBase
{
...
public ActionResult ItemSpec(int id, int dep, int cat, int tab)
{
// implementation that uses all four values
}
...
}
This is of course just one of the actions in it. There may be others as well. Most likely the Index one that's generated by default and is also used by default routing...

Related

Passing integer values from view to controller (mvc) through href

I 'm doing a dot net project (MVC) in which I want to pass integers (hard coded university ids) from view to Controller.
In view I 'm doing
PU
UET
GC
where admin is the CONTROLLER & applied is ACTION METHOD
in ACTION METHOD (applied in Admin)
public ActionResult applied(string uniId)
{
Processing of admissions on the basis of uniId
}
but when I 'm compiling this , uniId contains NULL instead of actual integer passed by PU etc.
Kindly help me out
ASP.NET MVC will only provide the value if the parameter is named id. You have to options. First is renaming the parameter:
public ActionResult applied(string id)
{
Processing of admissions on the basis of uniId
}
Second is creating a new route in RouteConfig above the default route:
routes.MapRoute(
"Applied", // Route name
"Admin/applied/{uniId}", // URL with parameters
new { controller = "Admin", action = "applied" } // Parameter defaults
);

Replace character in url before routing in ASP.NET MVC

Can I manipulate the url before routing it, i.e. before MVC goes through my route configuration to find the route to use.
I'd like to replace some characters in the url, for example "www.test.com/ä/ö" to "www.test.com/a/o". That way, if a user typed those letter in the url, the right route would still be used.
Maybe there´s something that I can hook into to manipulate the url?
Edit:
To clarify what I want I'll add an example. Let's say I have a routing configuration that looks like this: "{controller}/{action}". The user types www.test.com/MyCöntroller/MyÄction and I want to route that to the controller "MyController" and the action method "MyAction". I have to do the character replacement before the routing is done, otherwise no matching route will be found. Thus I'd like to replace all "ö" with "o" and all "ä" with "a" (and some more characters) BEFORE the routing is done. Is there any way to do this?
Edit2:
After some research it seems like it is UrlRoutingModule that is the first to get the url in ASP.NET MVC. Maybe there is some way to hook into that?
Take a loot at this post, by creating custom route handler it is possible.
using System.Web.Routing;
namespace My.Services
{
public class MyRouteHander : IRouteHandler
{
ApplicationDbContext Db = new ApplicationDbContext();
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// Get route data values
var routeData = requestContext.RouteData;
var action = routeData.GetRequiredString("action");
var controller = routeData.GetRequiredString("controller");
//modify your action name here
requestContext.RouteData.Values["action"] = actionName;
requestContext.RouteData.Values["controller"] = "SpecialController";
return new MvcHandler(requestContext);
}
}
}
Check out the answer to this question.
Basically you'll want to use the FilterAttribute with IActionFilter, and then apply the annotation to the ActionResult that services the route. This way you have an intermediary method to manipulate the URL before it's processed by your route configuration.

asp.net webapi url to identify same resource

I want to be able to identify a resource by different id types. for example:
GET http://example.com/customers/internalId=34 to go to
public Customer GetByInternalId(int internalId){...}
and
GET http://example.com/customers/externalId='JohnDoe' to go to
public Customer GetByExternalId(string externalId){...}
I know I can do this by having some parsing logic in a generic controller method but I don't want to do that. How do I achieve this using the routing feature of asp.net webapi if that is possible.
I would suggest that you try and avoid doing what you are suggesting. Creating two distinct URIs for the same resource will make it harder to use caching. Instead I would suggest using one URL to redirect to the other.
e.g.
> GET /customers/34
< 200 OK
> GET /Customers?name=JohnDoe
< 303 See Other
< Location: http://example.com/customers/34
Your methods do not make much of a sense, why would you return void from a method that begins with Get....?
Also, these routes:
http://example.com/customers/internalId=34
http://example.com/customers/externalId='JohnDoe
Are invalid from MVC/Web API perspective. This is how they should look like:
http://example.com/customers?internalId=34
http://example.com/customers?externalId=John
Default Web API routing should differentiate between the two and route it to different actions.
EDIT:
Create action with the following template:
[HttpGet]
public string InternalId(int id)
{
return id.ToString();
}
Define route for Web Api:
config.Routes.MapHttpRoute(
name: "Weird",
routeTemplate: "{controller}/{action}={id}",
defaults: new { id = RouteParameter.Optional }
);
This allows you to write:
http://localhost:7027/values/internalId=12
Try it...
Then you can just add another method:
[HttpGet]
public string ExternalId(string id)
{
return id;
}
And this:
http://localhost:7027/values/externalId=bob
Will work as well.
Clearly name of my controller is ValuesController as I've just tested this with default Web Api template.

ASP.NET MVC 3 Reroute to other controller and action & Restful API versioning

My original problem is I am looking what is the best practise to do versioning in Restful API. Not much people talk about this, dont have a good answer or I can't found exactly the solution at this moment.
(1) At first I am thinking to use Tag or Branch for each version http://domain.com/API/{version}. So if new API released, I Tag it, export and publish into the respective URL but seems hard to mix the different revision of source in one web application.
(2) Then I am thinking to use this way, one controller for one version:
(Just like this question Versioning of REST API Built With ASP.NET MVC 3 - Best Practices)
http://domain.com/API/1.0/{AnAction} => will go to APIV1Controller.{AnAction}
http://domain.com/API/2.0/{AnAction} => will go to APIV2Controller.{AnAction}
but it need to write a route for each version.
(3) Third way I get the idea from PayPal API which is the version is not in the URL but in the POST parameter. So the URL fixed to http://domain.com/API/ but user must specify the Version parameter to have "1.0" or "2.0".
The solution for this: The (2) is ok for me, and currently I use this way but I want to mixed the (2) and (3) so I have a APIController which only have one Index action to check this Version parameter and transfer the request to the respective controller and action either APIV1Controller.{AnAction} or APIV2Controller.{AnAction}.
After Googling and Stackoverflowing about how to transfer, invoke or call another controller and action without redirection. Seems there is no good answer and good practise. Someone answer .NET MVC Call method on different controller by simply creating new instance of the controller. Suddenly I got the idea how about to reroute!
The question:
Is it possible to reroute the the other controller and action from another action without redirection and how to do that?
Or a specific question, when user request http://domain.com/API/{AnAction} with Version="2.0", how can I reroute from APIController.Index to APIV2Controller.{AnAction}?
I am not using IoC.
This can be done via routing constraints. Firstly implement IRouteConstraint:
public class RequestParameterConstraint : IRouteConstraint
{
public string ParameterName { get; private set; }
public string ParameterValue { get; private set; }
public RequestParameterConstraint(string parameter, string value)
{
ParameterName = parameter;
ParameterValue = value;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection)
{
var value = httpContext.Request[ParameterName] ?? "";
return value.Equals(ParameterValue);
}
}
Then register routes:
routes.MapRoute(
"Version10",
"API/{action}/{id}",
new { controller = "APIV1", action = "Index", id = UrlParameter.Optional },
new { header = new RequestParameterConstraint("Version", "1.0") }
);
routes.MapRoute(
"Version20",
"API/{action}/{id}",
new { controller = "APIV2", action = "Index", id = UrlParameter.Optional },
new { header = new RequestParameterConstraint("Version", "2.0") }
);
That's all. This will do the trick.
http://coderjournal.com/2010/09/simple-rest-api-versioning-using-mef-and-mvc/
This seems to do exactly what you want, but it takes a very different approach by using a completely different set of controllers, rather than rerouting to them.
Hope this helps.

How do I set a "Default Action" for my Controller that will be called when no other action matches?

Say I have the following route:
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
Lets also say that my controller has the following methods: Index(Int32 id) and Edit(Int32 id).
So /MyController/Index/1 is a valid URL for that route. So is /MyController/Edit/1
However, if a URL is received that correctly maps to my controller but not to an existing action, how do I define a "Default Action" to execute instead of letting the MVC framework throw up an error screen?
Basically I'd like the URLs /MyController/Preview/1 and /MyController/Whatever/1 to execute an action that I specify ahead of time when the {action} token can't be mapped to an existing action on my controller.
I see that the MvcContrib project on Codeplex has an attribute that enables this for use with the ConventionController, but I'd like to keep this with pure MS ASP.NET MVC for now.
I also see that Fredrik mentions a [ControllerAction(DefaultAction = true)] attribute, but I can't find mention of it anywhere except his blog (and my app won't compile when I try it in my controller).
You can do the following for now.
protected override void HandleUnknownAction(string actionName) {
//your code here.
}
Another approach is that you put a constraint on the default route so it only matches methods you know exist on the controller. Then you could have another route like so:
routes.MapRoute("default-action", "{controller}/{actionName}/{id}", new {action="DefaultAction"});
Which maps to
public ActionResult DefaultAction(string actionName, string id) {
//handle default action
}
This gets you the result you're looking for.
Farooq Kaiser did an article on CodeProject on this topic which I found useful:
Handling Unknown Actions in ASP.NET MVC
I particularly like the trick of creating "view only" pages (obviously error handling code should be added):
protected override void HandleUnknownAction(string actionName)
{
this.View(actionName).ExecuteResult(ControllerContext);
}

Resources