Passing multiple parameters to a controller? - asp.net-mvc

ok. simple one that is wrapping my brain
I have a method that I have in the controller
public ActionResult Details(string strFirstName, string strLastName)
{
return View(repository.getListByFirstNameSurname(strFirstName, strLastName)
}
How do i get multiple parameters from the URL to the controller?
I dont want to use the QueryString as it seems to be non-mvc mind set.
Is there a Route? Or Other mechanism to make this work? Or am I missing something altogehter here with MVC
EDIT
the url that I am trying for is
http://site.com/search/details/FirstName and Surname
so if this was classic asp
http://site.com/search/details?FirstName+Surname
But i feel that i have missed understood something which in my haste to get to working code, I have missed the point that there really should be in a put request - and I should collect this from the formcollection.
Though might be worth while seeing if this can be done - for future reference =>

For example, suppose that you have an action method that calculates the distance between two points:
public void Distance(int x1, int y1, int x2, int y2)
{
double xSquared = Math.Pow(x2 - x1, 2);
double ySquared = Math.Pow(y2 - y1, 2);
Response.Write(Math.Sqrt(xSquared + ySquared));
}
Using only the default route, the request would need to look like this:
/simple/distance?x2=1&y2=2&x1=0&y1=0
We can improve on this by defining a route that allows you to specify the parameters in a cleaner format.
Add this code inside the RegisterRoutes methods within the Global.asax.cs.
routes.MapRoute("distance",
"simple/distance/{x1},{y1}/{x2},{y2}",
new { Controller = "Simple", action = "Distance" }
);
We can now call it using /simple/distance/0,0/1,2

Something like this?:
routes.MapRoute("TheRoute",
"{controller}/{action}/{strFirstName}/{strLastName}",
new { controller = "Home", action = "Index", strFirstName = "", strLastName = "" }
);
or:
routes.MapRoute("TheRoute2",
"people/details/{strFirstName}/{strLastName}",
new { controller = "people", action = "details", strFirstName = "", strLastName = "" }
);
UPDATED:
This route should be placed before "Default" route:
// for urls like http://site.com/search/details/FirstName/Surname
routes.MapRoute("TheRoute",
"search/details/{strFirstName}/{strLastName}",
new { controller = "search", action = "details", strFirstName = "", strLastName = "" }
);
routes.MapRoute("Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);

Use hidden values in your form
<%= Html.Hidden("strFirstName", Model.FirstName)%>
<%= Html.Hidden("strLastName", Model.LastName)%>
and the model binder will do the binding
public ActionResult Details(string strFirstName, string strLastName)
{
return View(repository.getListByFirstNameSurname(strFirstName, strLastName)
}

It is also possible to use FormCollection:
public ActionResult Details(int listId, FormCollection form)
{
return View(rep.getList(form["firstName"], form["lastName"])
}
Likewise, if the HTTP request contains a form value with the exact same name (case sensitive), it will automatically be passed into the ActionResult method.
Also, just to be clear, there is nothing un-MVC about querystring parameters.

I also had the same problem once and what I did was use the Ajax call inside the jQuery function. First I selected all parameter values using jQuery selectors. Below is my jQuery function.
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$('#btnSendNow').click(function () {
var grid = $('#Patient-kendo-Grid').data('kendoGrid');
var location = $('#EmailTempalteLocation option:selected').text();
var appoinmentType = $('#EmailTemplateAppoinmentType option:selected').text();
var emailTemplateId = $('#EmailTemplateDropdown').val();
var single = $('input:radio[name=rdbSingle]:checked').val();
var data = grid.dataSource.view();
var dataToSend = {
patients: data,
place: location,
appoinment: appoinmentType,
rdbsingle: single,
templateId: emailTemplateId
};
debugger;
$.ajax({
url: 'Controller/Action',
type: 'post',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(dataToSend)
});
});
});
</script>
My controller method has five parameters and it is as below.
[HttpPost]
public ActionResult SendEmailToMany(List<PatientModel> patients, string place, string appoinment, string rdbsingle, string templateId)
{
emailScheduleModel = new EmailScheduleModel();
AmazonSentEmailResultModel result;
List<string> _toEmailAddressList = new List<string>();
List<string> _ccEmailAddressList = new List<string>();
List<string> _bccEmailAddressList = new List<string>();
IEmailTemplateService emailTemplateService = new EmailTemplateService();
EmailTemplateContract template = emailTemplateService.GetEmailTemplateById(new Guid(templateId));
emailScheduleModel.EmailTemplateContract = new EmailTemplateContract();
emailScheduleModel.EmailTemplateContract = template;
}
It is working fine in my developments.
For further details please follow the below url.
http://dushanthamaduranga.blogspot.com/

Related

Html.ActionLink does not pass my id

In my view I have a ActionLink that passes an Id to another View. I used this multiple times but for some reason it does not work on this ActionLink. I even tried with a AJAX POST call in javascript but with no success either. Am I doing something wrong? If so, I am not seeing what.
Controller:
The parameter Id in this function is 0 and should be filled.
public ActionResult NieuwPriveBericht(int Id)
{
TblPER_Personeelslid Sender = BCL.GetEmployeeByLoginName(Session["LoginName"].ToString());
TblPER_Personeelslid Receiver = BCL.GetEmployeeById(Id);
var Model = new TblALG_PrvBericht();
Model.Datum = DateTime.Now.Date;
Model.Zender = Sender.IDPersoneelslid;
Model.Ontvanger = Receiver.IDPersoneelslid;
ViewBag.ReceiverName = Receiver.Voornaam + " " + Receiver.Naam;
return View(Model);
}
public ActionResult PriveBerichten()
{
ViewBag.SelectedEmployee = "";
var Model = new PriveBerichten();
return View(Model);
}
View:
If I debug my view I clearly see #Model.SelectedOption filled.
#using (Html.BeginForm("PriveBerichten", "Home", #Model, FormMethod.Post))
{
#Html.ActionLink("Nieuw bericht maken", "NieuwPriveBericht", new { Id = #Model.SelectedOption }, new { #class = "button-add" })
}
AJAX CALL
$("#DdlEmployees").change(function () {
var SelectedEmployee = $('#DdlEmployees option:selected').val();
$.ajax({
type: "POST",
url: 'PriveBerichten?SelectedEmployee=' + SelectedEmployee, // this works
dataType: "json",
data: $('form').serialize(),
success: function () {
alert("test"); // does not show
},
error: function () {
}
});
})
If you didn't set up the id of route is "Id", you need to use "id". Also delete "#Model" in the BeginForm.
Action
public ActionResult NieuwPriveBericht(int id)
{
//
}
View:
#using (Html.BeginForm("PriveBerichten", "Home", FormMethod.Post))
{
#Html.ActionLink("Nieuw bericht maken", "NieuwPriveBericht",
new { id = #Model.SelectedOption }, new{ #class = "button-add" })
}
Thanks for showing the ActionResult that generates the view. I think this is your problem:
var Model = new PriveBerichten();
return View(Model);
I assume your class PriveBerichten contains the SelectedOption property? If you do not change/initialize this property value in the constructor of PriveBerichten it is 0 by default, and so it will be 0 in your actionlink.

hide parameters passing to controller in address bar (URL rewrite or something else)

I have the following routes:
routes.MapRoute("Event Overview", "{city}/{type}/{id}",
new {city="LA", controller = "BaseEvent", action = "EventOverview"}, new {city = new CityConstraint()});
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
And, several links on my site:
#Html.ActionLink("Make", "EventOverview", "BaseEvent", new { id = eventInfo.Key.OID, type = eventInfo.Key.XPObjectType.TypeName.GetShortTypeName(), activeTab = "#scheduleLink", session = eventInfo.Key.EventSchedules[0].SessionId, hall = eventInfo.Key.EventSchedules[0].HallId, client = eventInfo.Key.EventSchedules[0].BasePlace.PremieraClientId}, null)
#Html.ActionLink("Make", "EventOverview", "BaseEvent", new { id = eventInfo.Key.OID, type = eventInfo.Key.XPObjectType.TypeName.GetShortTypeName(), activeTab = "#scheduleLink", }, null)
This is `EventOverview action:
public ActionResult EventOverview(int id, string type, string activeTab,string hall, string session, string client, string count)
{
var model = CreateEventViewData<EventViewData>(id, type);
model.ActiveTab = activeTab;
model.ScheduleCount = count;
model.SessionId = session;
model.HallId = hall;
model.ClientId = client;
return View("Controls/EventsInfo/EventInfo", model);
}
In the first link passing many parameters, and all shows in browser's address field:
This is for firts link:
http://localhost:62291/LA/Film/36?activeTab=%23scheduleLink&session=15&hall=65&client=2&count=1
This is for second link:
http://localhost:62291/LA/Film/36?activeTab=%23scheduleLink
I want something like that:
http://localhost:62291/LA/Film/36
What ways to hide parameters in an address line are?
UPDATE:
$(document).ready(function () {
var link = $(".btn_buy_ticket").find("a").click(function (e) {
e.preventDefault();
$.post($(this).attr("href"));
});
})
[HttpPost]
public ActionResult EventOverview(int id) // just for test
{
return RedirectToAction("EventOverview", new {id = id});
}
public ActionResult EventOverview(int id, string type, string activeTab,string hall, string session, string client, string count)
{
var model = CreateEventViewData<EventViewData>(id, type);
model.ActiveTab = activeTab;
model.ScheduleCount = count;
model.SessionId = session;
model.HallId = hall;
model.ClientId = client;
return View("Controls/EventsInfo/EventInfo", model);
}
All actions are called, but my EventInfo view not loaded.
You could use POST instead of GET. So you could replace the link with a form containing hidden fields for the parameters that you don't want to appear in the query string:
#using (Html.BeginForm("EventOverview", "BaseEvent", new { id = eventInfo.Key.OID, type = eventInfo.Key.XPObjectType.TypeName.GetShortTypeName() }, FormMethod.Post, null))
{
#Html.Hidden("activeTab", "#scheduleLink")
#Html.Hidden("session", eventInfo.Key.EventSchedules[0].SessionId)
#Html.Hidden("hall", eventInfo.Key.EventSchedules[0].HallId)
#Html.Hidden("client", eventInfo.Key.EventSchedules[0].BasePlace.PremieraClientId)
<button type="submit">Make</button>
}
How to hide URL Parameters
If you want to hide URL parameters, you go to debug properties and you select the radiobutton option and specify thatc
specificpage:
http://localhost:61757/TicketDataUpload/templateupload?projectid=6497&userid=7336
This is the parameter URL. If you want to hide like this:
http://localhost:61757/Controller/index
You have to put in a specific page as when you open the page, it will not display URL parameters.
My (kinda ugly) solution: leave the code behind as is, then after the html doc has loaded (at which point the server has already made use of your query string data), use history.pushState in javascript to change the url in the address bar like so:
$(document).ready(function () {
let hrefWithoutQueryString = window.location.href.split('?')[0];
// args below are 'state' (irrelevant for me), 'title' (so far,
// ignored by most browsers) and 'url' (will appear in address bar)
history.pushState({ }, '', hrefWithoutQueryString);
});
For a split second the query string will appear in the address bar, but after the js above has run, everything including and after the '?' in your url will be gone.
Obviously, a side effect is that it alters your browser's session history but this wasn't an issue for me.
And note that I have passed in an empty state into pushState--again, this was not an issue for me but could cause problems depending on how the routing of your application is set up and whether it makes use of the state variable.

Silverlight - Routing question

I have the following route in global.asax:
routes.MapRoute(
"IdeaShort",
"Idea/{id}",
new { PortalID = NEOGOV_Ideas.Models.Util.DefaultPortal().PortalID, IdeaType = "All", controller = "Home", action = "Idea", id = "" });
one problem - PortalID and IdeaType is linked with Idea, so I should get Idea from id before set PortalID and IdeaType. How to do it? Thanks
Just don't make PortalID and IdeaType incoming parameters of your action, but rather determine them inside the action method:
public ActionResult Idea(int id)
{
var PortalID = GetPortalID(id); //get PortalID here
var IdeaType = GetIdeaType(id); //get IdeaType here
//go on with the whole set of parameters you need
}

asp .net mvc routing url with custom literal

Is it possible to make url with custom literal separator that can have default parameters ?
context.MapRoute(
"Forums_links",
"Forum/{forumId}-{name}",
new { area = "Forums", action = "Index", controller = "Forum" },
new[] { "Jami.Web.Areas.Forums.Controllers" }
);
I have this as you see im using to dash to separate id from name so I can have url like:
/Forum/1-forum-name
Instead of:
/Forum/1/forum-name
I see the problem is I'm using multiple dashes. And routing engine don't know which one to separate. But overalll it doesn't change my question because I want to use multiple dashes anyway.
Very interesting question.
The only way I could come up with is much like Daniel's, with one extra feature.
context.MapRoute(
"Forums_links",
"Forum/{forumIdAndName}",
new { area = "Forums", action = "Index", controller = "Forum" },
new { item = #"^\d+-(([a-zA-Z0-9]+)-)*([a-zA-Z0-9]+)$" } //constraint
new[] { "Jami.Web.Areas.Forums.Controllers" }
);
That way, the only items that will get matched to this route are ones formatted in the pattern of:
[one or more digit]-[zero or more repeating groups of string separated by dashes]-[final string]
From here you would use the method Daniel posted to parse the data you need from the forumIdAndName parameter.
One way to achieve this could be by combining id and name into the same route value:
context.MapRoute(
"Forums_links",
"Forum/{forumIdAndName}",
new { area = "Forums", action = "Index", controller = "Forum" },
new[] { "Jami.Web.Areas.Forums.Controllers" }
);
And then extract the Id from it:
private static int? GetForumId(string forumIdAndName)
{
int i = forumIdAndName.IndexOf("-");
if (i < 1) return null;
string s = forumIdAndName.Substring(0, i);
int id;
if (!int.TryParse(s, out id)) return null;
return id;
}

ASP.NET MVC: Route to URL

What's the easiest way to get the URL (relative or absolute) to a Route in MVC? I saw this code here on SO but it seems a little verbose and doesn't enumerate the RouteTable.
Example:
List<string> urlList = new List<string>();
urlList.Add(GetUrl(new { controller = "Help", action = "Edit" }));
urlList.Add(GetUrl(new { controller = "Help", action = "Create" }));
urlList.Add(GetUrl(new { controller = "About", action = "Company" }));
urlList.Add(GetUrl(new { controller = "About", action = "Management" }));
With:
protected string GetUrl(object routeValues)
{
RouteValueDictionary values = new RouteValueDictionary(routeValues);
RequestContext context = new RequestContext(HttpContext, RouteData);
string url = RouteTable.Routes.GetVirtualPath(context, values).VirtualPath;
return new Uri(Request.Url, url).AbsoluteUri;
}
What's a better way to examine the RouteTable and get a URL for a given controller and action?
Use the UrlHelper class: http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.aspx
You should be able to use it via the Url object in your controller. To map to an action, use the Action method: Url.Action("actionName","controllerName");.
A full list of overloads for the Action method is here: http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.action.aspx
so your code would look like this:
List<string> urlList = new List<string>();
urlList.Add(Url.Action("Edit", "Help"));
urlList.Add(Url.Action("Create", "Help"));
urlList.Add(Url.Action("Company", "About"));
urlList.Add(Url.Action("Management", "About"));
EDIT: It seems, from your new answer, that your trying to build a sitemap.
Have a look at this Codeplex project: http://mvcsitemap.codeplex.com/. I haven't used it myself, but it looks pretty solid.
How about this (in the controller):
public IEnumerable<SiteMapEntry> SiteMapEntries
{
get
{
var entries = new List<SiteMapEntry>();
foreach (var route in this.Routes)
{
entries.Add(new SiteMapEntry
(
this.Url.RouteUrl(route.Defaults),
SiteMapEntry.ChangeFrequency.Weekly,
DateTime.Now,
1F));
}
return entries;
}
}
Where the controller has member:
public IEnumerable<Route> Routes
Take note of:
this.Url.RouteUrl(route.Defaults)

Resources