MVC Routing System - c#

What means the operator : when calling methods for example ? I see that it maps the name of the parameter's name inside the method. What means name : "Default" how to interpret it ? What is the name of this kind of calling method ?
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

That is called "named arguments", and I would not call it an operator. (There is a ?: operator though)
Named and Optional Arguments (C# Programming Guide)

Related

MVC Route Parameters Are Null

I'm receiving the following error that my default route parameters are null. I've used this same code on a Controller Action that didn't have any parameters in the URL and it worked fine. I know that my custom route is being called but I don't understand why startIndex and pageSize are showing up null in the action.
Error:
The parameters dictionary contains a null entry for parameter 'startIndex' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult ViewVcByStatus(System.String, Int32, Int32)' in 'AEO.WorkOrder.WebUI.Controllers.VendorComplianceController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Controller:
public ActionResult ViewVcByStatus(string status, int startIndex, int pageSize) { ... }
Route:
routes.MapRoute("ViewVcByStatus", "ViewVcByStatus/{status}",
new
{
controller = "VendorCompliance",
action = "ViewVcByStatus",
startIndex = 0,
pageSize = WebConfigurationManager.AppSettings["PageSize"],
});
Link:
<a href="VendorCompliance/ViewVcByStatus?status=PROCESSED">
Also tried this link which produces the same error:
<a href="VendorCompliance/ViewVcByStatus/PROCESSED">
Try this.
public ActionResult ViewVcByStatus(string status, int? pageSize, int?startIndex)
{
return View();
}
Route.config
routes.MapRoute(
name: "ViewVcByStatus",
url: "ViewVcByStatus/{status}",
defaults: new { controller = "VendorCompliance", action = "ViewVcByStatus", startIndex = UrlParameter.Optional, pageSize = UrlParameter.Optional });
optional parameters should be declared optional in routeconfig and mark them int? in your action method, This will do the work for you. Hope this helps.This solution will work with your url pattern in your question "http://localhost:53290/VendorCompliance/ViewVcByStatus?status=PROCESSED".
Send the startIndex and pageSize with the link(I hardcoded it, use parameters instead), your actionresult is expecting all parameters that the link needs to provide, and the MapRoute will probably fall through to default Route because it can´t match it with any other route matching the one parameter you provided
<a href="VendorCompliance/ViewVcByStatus?status=PROCESSED&startIndex=0&pageSize=0">

LINQ query cannot evaluate GET parameter in StartsWith

I'm trying to make a query through a GET request (in Angular.js) using .NET Web API and Entity Framework using LINQ and MySQL db.
http://localhost/ProductsApp/api/clientes/GetByName/M
The problems is that the parameter passed by GET is not evaluated and I don't get any results (even though name is being set correctly to "M" according to the debugger).
However, if I hardcode a string, I get the expected result.
[ActionName("GetByName")]
public IEnumerable<cliente> GetByName(string name)
{
var query = from c in context.clientes where c.nome.StartsWith(name) select c;
var query2 = from c in context.clientes where c.nome.StartsWith("M") select c;
var query3 = context.clientes.Where(c => c.nome.StartsWith(name));
var query4 = context.clientes.Where(c => c.nome.StartsWith("M"));
return query.ToList();
}
My WebApiConfig.cs has the following lines:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{name}",
defaults: null
);
I suppose that LINQ resolves the variables when it is executed, as hinted below (I removed the unimportant part of the query):
query.ToString()
"SELECT [...] WHERE `Extent1`.`nome` LIKE 'p__linq__0%'"
query2.ToString()
"SELECT [...] WHERE `Extent1`.`nome` LIKE 'M%'"
query3.ToString()
"SELECT [...] WHERE `Extent1`.`nome` LIKE 'p__linq__0%'"
query4.ToString()
"SELECT [...] WHERE `Extent1`.`nome` LIKE 'M%'"
Both query2 and query4 return correct values while query and query3 do not. Why? How can I make it work?
This is a reported bug with MySQL Entity Framework 6.9.5
Bug #74918 : Incorrect query result with Entity Framework 6:
https://bugs.mysql.com/bug.php?id=74918
It has been fixed in MySQL Connector/Net 6.7.7 / 6.8.5 / 6.9.6 releases.
Changelog:
With Entity Framework 6, passing in a string reference to the "StartWith"
clause would return incorrect results.
Alternatively, a workaround is to use .Substring(0) which forces Entity not to use LIKE (might affect performance).
var query = context.clientes.Where(c => c.nome.StartsWith(name.Substring(0)));
Your name parameter does not equal to "M", it is possible that this value is null. WebApi probably expects a "id" parameter and not "name"
Add a route attribute to make sure that the correct value is passed to the name parameter
[Route("api/clientes/GetByName/{name}")]
public IEnumerable<cliente> GetByName(string name)
{
....
}
If you have more than one GET method with parameter so you have to change your WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
or another way to do this you have to hardcode your controller and action in WebApiConfig.cs like this
config.Routes.MapHttpRoute(
name: "GetApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "GetByName", controller = "Your Controller" });
Your Action:
[HttpGet]
public IEnumerable<cliente> GetByName(string name)
{
}
Call it like this
$.ajax({
type: 'GET',
url: 'localhost/ProductsApp/api/clientes/GetByName?Name='+ M,
data: JSON.stringify({}),
contentType: 'application/json',
dataType: 'json',
success: function (data) {
}
}
});

Web.API MapHttpRoute parameters

I'm having problems with my Web.API routing. I have the following two routes:
config.Routes.MapHttpRoute(
name: "MethodOne",
routeTemplate: "api/{controller}/{action}/{id}/{type}",
defaults: new { id = RouteParameter.Optional, type = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "MethodTwo",
routeTemplate: "api/{controller}/{action}/{directory}/{report}",
defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
);
And in my controller these two methods:
[HttpGet]
[ActionName("methodone")]
public string MethodOne(string id, string type)
{
return string.Empty;
}
[HttpGet]
[ActionName("methodtwo")]
public string MethodTwo(string directory, string report)
{
return string.Empty;
}
These two seemingly cannot live side by side. If I comment out the MethodOne route in WebApiConfig, the MethodTwo route works. Commenting MethodTwo route allows MethodOne to work. Leaving both uncommented, MethodOne works, but not MethodTwo.
I was hoping to use one route for both of these then it seems they would have to have the same parameter names. Who writes methods with generic parameter names? Bad. I really don't want my methods to have the same parameter names (like p1, p2, p3), so I thought I could create a route just for the new method. But even this doesn't seem to work.
I really miss the WebGet(UriTemplate="") from WCF rest.
I have one controller that has many methods, some with 1, 2, 3 or even more parameters. I can't believe I cant use meaningful parameter names with the MapHttpRoute approach.
I could comment that stuff out entirely and use WebGet() … but before I got there I wanted to see if I'm missing something.
The reason you are seeing this problem is because your first route will match both requests. The id and type token in the URL will match both requests because when the route is being run, it will try parse the URL and match each segment against your URL.
So your first route will happily match both requests as follows.
~/methodone/1/mytype => action = methodone, id = 1, and type = mytype
~/methodtwo/directory/report => action = methodtwo, id = directory, and type = report
To work around this, you should use route like
config.Routes.MapHttpRoute(
name: "MethodOne",
routeTemplate: "api/{controller}/methodone/{id}/{type}",
defaults: new { id = RouteParameter.Optional, type = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "MethodTwo",
routeTemplate: "api/{controller}/methodtwo/{directory}/{report}",
defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
);
Even if you use WebGet, you might need to do something similarly to disambiguous those two methods I believe.
You can choose to pass the parameters in the query string like /MethodTwo?directory=a&report=b, but if you'd rather they show up in the path, this looks like a good candidate for attribute-based routing. Filip has a great post about it here:
http://www.strathweb.com/2012/05/attribute-based-routing-in-asp-net-web-api/
From http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
You can also provide constraints, which restrict how a URI segment can
match a placeholder:
constraints: new { id = #"\d+" } // Only matches if "id" is one or
more digits.
Adding this constraint to "MethodOne" (api/{controller}/{action}/{id}/{type}) would mean that numbers it only matches if {id} is a number otherwise it would match "MethodTwo" ("api/{controller}/{action}/{directory}/{report}").

When I enter localhost/MyController/MyActionName/1 i get a null in the optional parameter why?

SOLUTION
the route
routes.MapRoute(
"Whatever", // Route name
"{controller}/{action}/{id}", //{ID} MUST BE USED IN YOUR CONTROLLER AS THE PARAMETER
new { controller = "MyController", action = "MyActionName", id = UrlParameter.Optional } // Parameter defaults
);
And that's it! I guess you must use the name of the id in the
public actionresult(int id //must be ID HERE like global.asax)
Steps to reproduce my problem:
1. Create a new mvc3 application
2. Go to home controller and put Index(int? x){ return view()}
3. Run the application
4. Go to the url type in the url http://localthost:someport/Home/Index/1
5. Insert a break point in controller to see the value of x
6. Notice that even if you put the url above x NOT equal to 1 as is suppose to!
I just dont understand why i am getting a null in the id....
public ActionResult MyActionName(int? id)
{
//the id is null!!!!!!!!!!!! event thought i just entered the url below!
}
I enter the following url in my browser
http://locahost/MyController/MyActionName/1
//I also put this in my global.asax but it doesnt really help.
routes.MapRoute(
"Whatever", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "MyController", action = "MyActionName", id = UrlParameter.Optional } // Parameter defaults
);
AND!
My error if I put
public ActionResult MyActionName(int id)
{
//the id is null!!!!!!!!!!!! event thought i just entered the url below!
}
Note that the above example was made for simplicity this error is for the actual application.
Server Error in '/' Application.
The parameters dictionary contains a null entry for parameter 'MvrId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Index(Int32)' in 'MedicalVariance.Controllers.MedicineManagementController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: The parameters dictionary contains a null entry for parameter 'MvrId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Index(Int32)' in 'MedicalVariance.Controllers.MedicineManagementController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Make sure your route is defined before the default route.

ASP.NET MVC ignore route value

I have the following route: {param1}/{param2}/{param3} and I want to bind it to action which doesn't have param1 parameter (it doesn't matter for it). If I just don't define param1 parameter in the action method, route won't be chosen by ASP.NET MVC. So now I have to define param1 parameter in the action and just don't use it.
Is there any way to ignore some route values to not have to define them in action methods?
Why don't you reorder your parameters so that it goes:
routes.MapRoute(
//// Route name
"myNewRoute",
//// URL with parameters
"{param2}/{param3}/{param1}",
//// Parameter defaults
new { controller = "MyController", action = "MyActionName", param2 = string.Empty, param3 = string.Empty, param1 = string.Empty });
Now if you supply only the first two parameters, it takes param2 and param3. param1 defaults to string.empty.
If you supply all three parameters, then param1, param2, and param3 will all have values.
A second approach would be to use a 2 MapRoutes. Note that I added "Custom" to the route here, to ensure that the routing engine can differentiate between this route and routes that take three parameters and should go to the default asp mvc route.
I also placed Route1 before Route2 so the routing engine, if it sees 2 parameters, would prefer this route over Route2. if you supply 3 parameters, the route will prefer Route2 over Route1 or the default mvc route.
routes.MapRoute(
//// Route name
"Route1",
//// URL with parameters
"Custom/{param2}/{param3}",
//// Parameter defaults
new { controller = "MyController", action = "MyActionName", param2 = string.Empty, param3 = string.Empty });
routes.MapRoute(
//// Route name
"Route2",
//// URL with parameters
"Custom/{param1}/{param2}/{param3}",
//// Parameter defaults
new { controller = "MyController", action = "MyActionName", param2 = string.Empty, param3 = string.Empty, param1 = string.Empty });

Categories

Resources