Can't get multiple parameters to controller to work - c#

Here's the jquery from my view:
$("#btnSelect1").click(function () {
var donationTypeID = $(this).closest('p').find('#selectList').val();
var id = parseInt(donationTypeID);
var id2 = $('#person').val();
var persId = parseInt(id2);
// var personName
var route = '/Donation/ContinueDonation/' + id + '?personId =' + persId;
$("#donationSection1").load(route, function () {...});...
Here's the controller method
public ActionResult ContinueDonation(int id, int personId)
{}
Any thoughts on how I can get this to work? Thanks

I actually think the previous answer is not all that right. Your query string is correct if it were hitting the default route established by MVC which matches a URL something like this {controller}/{action}/{id}.
What must really be going on is that you messed with the routes and your query is either not hitting the default route or you changed that.
What I would do is get the RouteDebugger (just get it via nuget) and see which route your query string hits. You could setup a route for any URL you want it to be (sort of the whole point of friendly URLs), so If you want the route to be /ContinueGiving/{id}/{personId} you can do that by adding a route to the beginning of the routes getting added with a definition something like this:
routes.MapRoute(
name: "ContinueDonation",
url: "ContinueGiving/{id}/{personId}",
defaults: new { controller = "Donation", action = "ContinueDonation" },
constraints: new { id = #"\d+", personId = #"\d+" }
);
Any parameters you do not specify will get mapped if the framework can find any matching items in either posted values, the query string, etc.
The constraints make sure this route only gets matched if the parameters passed are numbers.
So the previous answer worked because somehow the route with id didn't match, but that is not really your issue.

You didn't give a key to the id value:
var route = '/Donation/ContinueDonation/?id=' + id + '&personId =' + persId;
BTW, the var persId = parseInt(id2); line is redundant, as every parameter sent with HTTP is a string, so "234" and 234 are exactly the same.

Related

How do i pass multiple parameters to c# method from browser URL

I ad trying to pass parameters to call the following C# method
public ActionResult GenerateInvoicePDFByInvoiceNum(string id,string apikey)
{
IInvoiceRepository rep = db.GetInvoiceRepository();
//
var api = Guid.Parse(apikey);
Invoice invoice = rep.GetByExpression(i => i.InvoiceNo.Equals(id) && i.Visit.Branch.Practice.APIKey.ToString().Equals(apikey)).FirstOrDefault();
if (invoice==null)
{
return HttpNotFound();
}
//return new Rotativa.ActionAsPdf("PrintInvoice", new { id = invoice.Id })
//{
// //CustomSwitches = "--load-error-handling ignore "
// CustomSwitches = "--disable-javascript"
//};
return RedirectToAction("GenerateInvoicePDF", new { id = invoice.Hash });
}
From the browser I am trying to call it with a call like this which worked when I had only one parameter, but I don't know how to change those to pass the second parameter
http://foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum/72341d
Thanks
On your url: http://foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum/72341d
"/72341d" represents an optional parameter.
Try to pass a query string.
To do that, you need to specify the parameter name and value you want to pass.
http://foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum?id=72341d&apikey=YOUR_API_KEY
This is how you pass parameters by url:
http://foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum?id=72341d&apikey=yourapikeygoeshere
You can pass multiple parameters as "?param1=value1&param2=value2"
http://foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum?id=1&1pikey=2
You have three choices to do this:
Pass parameters using query string like /?id=value&apikey=value
Add a custom route in "RouteConfig" (~/App_Start/RouteConfig.cs) like below:
routes.MapRoute(
name: "RouteName",
url: "{controller}/{action}/{id}/{apikey}"
);
Use attribute routing. To do this first enable it by calling the "routes.MapMvcAttributeRoutes()" method in "RouteConfig" and then apply the [Route(urlPttern)] attribute to the related action and pass the url pattern to the method
after applying solution 2 or 3 you can pass parameters in url like:
"/foobar.n.co.za/Newlook/PrintInvoice/GenerateInvoicePDFByInvoiceNum/72341d/apikeyvalue"

Basic Conventional routing asp.net webapi

I have a simple query on ASP.Net Web API Routing. I have the following controller:
public class CustomersController: ApiController
{
public List<SomeClass> Get(string searchTerm)
{
if(String.IsNullOrEmpty(searchTerm))
{
//return complete List
}
else
{
//return list.where (Customer name contains searchTerm)
}
}
}
My routing configuration (Conventional) looks like this:
config.Routes.MapHttpRoute(name:"DefaultApi",
routeTemplate:"api/{controller}/{id}"
defaults:new {id = RouteParameter.Optional});
config.Routes.MapHttpRoute(name:"CustomersApi",
routeTemplate:"api/{controller}/{searchTerm}"
defaults:new {searchTerm = RouteParameter.Optional});
If I hit the url:
http://localhost:57169/api/Customers/Vi
I get a 404-Not found
If I reverse the order of the routes, it works.
So the question is in the first case, is it matching the first route (DefaultApi)? If not, why is it not trying the second route?
This route template
config.Routes.MapHttpRoute(name:"DefaultApi",
routeTemplate:"api/{controller}/{id}",
defaults:new {id = RouteParameter.Optional}
);
match your URL because Id can be any type : string, int etc. So your URL respect this template and this route is chosen.
To make this template more restrcitive and make ASP.Net Web API to go to the next template you need to add to it some constraints by saying something like "Id parameter must be a numeric type for this template". So you add constraints parameter like below:
config.Routes.MapHttpRoute(name:"DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Required}, // <- also here I put Required to make sure that when your user doesn't give searchTerm so this template will not be chosen.
constraints: new {id = #"\d+"} // <- regular expression is used to say that id must be numeric value for this template.
);
So by using this URL http://localhost:57169/api/Customers/Vi the above template will be skipped and the next will be chosen.

ASP.NET MVC routing without unnecessary text

I have a problem with my MVC. Think like a URL.
domain.com/product/any-product/1
domain.com/category/any-category/1
Can I change url like this?:
domain.com/any-product/1
domain.com/any-category/1
Also can I delete id?
context.MapRoute(
name: "category",
url: "category/{category_name}/{category_id}",
defaults: new
{
controller = "Cateogory",
action = "Index",
Area = "Shop"
}
);
context.MapRoute(
name: "product_detail",
url: "product/{category}/{product_name}/{product_id}",
defaults: new
{
controller = "Product",
action = "ProductDetail",
Area = "Shop",
product_name = UrlParameter.Optional,
product_id = UrlParameter.Optional
}
);
No, you can't do it exactly like that, but you can get closer. Think for a second about what you're saying you want:
/any-product/ => ProductController
/any-category/ => CategoryController
Now, logically speaking, how is MVC supposed to sort out which URL is referring to a product and which is referring to a category?
You could do something like:
/any-category/ => CategoryController
/any-category/any-product/ = > ProductController
Now, there's some way to for MVC to work out that the URLs are different. If there's something after the category part of the path, then it's a product.
As for removing the id portion, that depends. The point of the id in the first place is that you need some sort of unique identifier for a record that should be loaded. If "any-product" is a string that can uniquely identify the record (you have column in the database with that value and there's only one with that value), then you can use that string to look up the entity instead. Then, no, you no longer need the id portion of the URL. However, if the string is not unique or doesn't correspond to data in the database, then you need the id to locate the record, and it cannot be removed.

ASP.NET MVC URL Routes

In ASP.NET MVC, is it possible to define routes that can determine which controller to use based on the data type of part of the URL?
For example:
routes.MapRoute("Integer", "{myInteger}", new { controller = "Integer", action = "ProcessInteger", myInteger = "" });
routes.MapRoute("String", "{myString}", new { controller = "String", action = "ProcessString", myString = "" });
Essentially, I want the following URLs to be handled by different controllers even though they have the same number of parts:
mydomain/123
mydomain/ABC
P.S. The above code doesn't work but it's indicative of what I want to acheive.
Yes, if you use constraints:
like so:
routes.MapRoute(
"Integers",
"{myInteger}",
new { controller = "Integer", action = "ProcessInteger"},
new { myInteger = #"\d+" }
);
If you put that route above your string route (that doesn't contain the constraint for #"\d+"), then it'll filter out any routes containing integers, and anything that doesn't have integers will be passed through and your string route will pick it up.
The real trick is that Routes can filter what's coming through based on Regular Expressions, and that's how you can determine what should pick it up.

Why the query strings in my ASP.NET MVC route?

On an ASP.NET MVC (Beta) site that I am developing sometimes calls to ActionLink will return to me URLs containing querying strings. I have isolated the circumstances that produce this behavior, but I still do not understand why, instead of producing a clean URL, it decides to using a query string parameter. I know that functionally they are the same, but for consistency (and appearance) of the URLs this is not what I want.
Here are my routes:
routes.MapRoute(
"Photo Gallery Shortcut",
"group/{groupname}",
new { controller = "Photos", action = "All", Id = "" });
routes.MapRoute(
"Tagged Photos", //since the Tagged action takes an extra parameter, put it first
"group/{groupname}/Photos/Tagged/{tagname}/{sortby}",
new { controller = "Photos", action = "Tagged", Id = "", SortBy = "" });
routes.MapRoute(
"Photo Gallery", //since the Gallery's defualt action is "All" not "Index" its listed seperatly
"group/{groupname}/Photos/{action}/{sortby}",
new { controller = "Photos", action = "All", Id = "", SortBy = "" });
routes.MapRoute(
"Group", //<-- "Group" Category defined above
"group/{groupname}/{controller}/{action}/{id}",
new {controller = "Photos", action = "Index", Id = ""});
Now the problem only occurs when I am looking at the view described by the route named "Tagged Photos" and execute ActionLink via:
Html.ActionLink<PhotosController>(p => p.All((string)ViewData["group"], ""), "Home")
Which produces the URL:
http://domain/group/GROUPNAME?sortBy=
From any other view the URL produced is:
http://domain/group/GROUPNAME
I have pulled down Phil's ASP.NET Routing Debugger, and everything appears in order. This one has me stumped. Any ideas?
Not sure why different views are producing different URLs.
But you can get rid of that sortBy param by assigning a default value to the first route.
new { sortBy = "" }
During generation, if sortBy matches the default, the route engine will skip that parameter (if it's in the query string).
You're going to have to use named routes here, not action routes, because of the way routing works in ASP.NET, because it does "first match", not "best match".
I think it is picking up your first Route. It too has the action All. And because the sortby is not specified it is exposing it as a querystring parameter
This will still work with the action method 'All' on the PhotosController, because it just fills the sortby parameter with the query string value.
In the Route Debugger is it executing the 3rd route or the 1st?

Categories