I have an action method with the following signature,
ActionResult Search(string searchQuery)
This gets called from a partial view on button submit from a form. Problem is, please look at the 2 patterns below. When I submit my search key from my page it uses the following url (suppose search key is tool)
Search/?searchQuery=tool
But then if I click on a tool then,
Search/tool?searchQuery=garden
Now my method is reading tool in the parameter instead of garden (which is expected of course). I presume this is to do with incorrect presentation of items from both the context of the item itself and that of search.
Is there a nice way of resolving this issue? I want to read the query string term and search for it from the main search context i.e. Search/?searchQuery=<term> no matter where I am.
To get the QueryString, in your controller you should write something like this:
var mystring =Request.QueryString["searchQuery"];
This will get the query string no matter where is placed in your url.
Rename the input to
ActionResult Search(string searchQuery)
The model binder will then deserialize the query string param to that input value. It will work for both route params and query string params.
Related
I had to pass an extra parameter with my action links to indicate where they came from (as I needed to change a back link in the pages accordingly).
As it was a controller name, I decided to name it controller.
e.g. a sample link might be:
#Html.ActionLink(item.Name, "Options", "Questionnaire", new {
id = item.QuestionnaireId,
controller = "templates" }, null)
The receiving action in QuestionnaireController looked like:
public ActionResult Options(int id, string controller)
When the action was hit I noticed the controller value was not template, but instead was the name of the current controller (i.e. QuestionnaireController).
As an experiment I added an action parameter e.g.:
public ActionResult Options(int id, string controller, string action)
the action value was the current action too (i.e. Options).
My work-around for this was simply to rename my parameter to source, but why does MVC bother to map the names controller and action to action parameters? I assume that would apply to any/all Route Mapping values, but what is the purpose of this?
Why does MVC bother to map the names controller and action to action parameters?
I believe it's done as part of the QueryStringValueProvider or one of the other ValueProviders (maybe the RouteDataValueProvider). ASP.Net MVC uses Convention over Configuration, so the framework uses the values provided to populate method parameters. The Controller name, Action name and even the Area name are all values provided in the Url.
I assume that would apply to any/all Route Mapping values, but what is the purpose of this?
The ValueProvider is used for Routing data to determine the matching route to use, it also happens to be the same object that provides the data to populate method parameters. The side affect you are experiencing is most likely not a feature they were trying to implement.
The DefaultModelBinder.GetValue uses the ValueProviders to locate a value and bind it to the model (or method paramater).
I've defined such a controller ViewProfile.
I want to use it for the next syntax to access public user info in my project.
/ViewProfile/Sammy
/ViewProfile/Billy
etc...
But I don't know how to handle the 2-nd parameter in URL.
I've tried to use:
[HttpGet]
public ActionResult Index(string query)
{
...
return View();
}
But in the debugger, string query is always empty.
I have read about routines mapping, but really don't understand how would it help me with the determination of id or other parameters.
I read in ASP.NET MVC Book that to get the parameter directly in the controller action just name it as ID.
ASP.NET MVC lets you easily do this without having to confi gure
anything extra. ASP .NET MVC’s default routing convention is to treat
the segment of a URL after the action method name as a parameter named
ID. If your action method has a parameter named ID, then ASP.NET MVC
will automatically pass the URL segment to you as a parameter.
I just tried a sample app and it worked fine for me. The string i entered in the URL did get passed on to the ID parameter in the action.
Also what i noticed is that you should provide your URL as viewprofile/index/1 or
viewprofile/index/somestring.
YOu seem to be skipping the action part.
I have a details page containing a form field named UserId. On the same page i have another search form with a field also named UserId.
I am using Html.LabelFor(vm > vm.UserId) and Html.TextBoxFor(sm > sm.UserId) on the two different view models, vm being the view model and sm being the search model. (Yes, the UserId property on the two models has identical names - because they are the same domain property.
When i navigate to the page, the populated UserId on the vm is inserted into BOTH form fields named UserId by MVC. Even the sm.UserId are empty.
That is my initial problem. There are a few ways ti avoid that. My solution was to use the Prefix flag for the sm.
[HttpGet]
public ActionResult Search([Bind(Prefix = "Search")] SearchFormViewModel searchFormViewModel, PagingViewModel pagingViewModel)
{
This will provoke MVC to render a Search.UserId on the fieldname in the search form, but the property in code will still be named UserId.
This solution seems to work great!
BUT:
Now i have to address the search.UserId on a route from Global.asax.
I map the route like this:
routes.MapRoute(
"MyRouteName",
"ControllerName/User/{Search.UserId}",
new { controller = "ControllerName", action = "Search" }
);
My problem is that MVC can't map the Search.UserId (because of the .) to fit the UserId (prefixed with Search) in the action shown above.
So it seems like MVC has a prefix-feature, that are actually nok fully supported through the Route-handler.
Ofcourse i could rename the Search.UserId to Search_UserId, but then the name dosent match the name MVC expects in the recieving action above. (expects Search.UserId) Renaming The UserId property of the search model would fix the issue, but since it is the same value in the domain, this seems like a workaround.
Am I missing something here about the usage of the Prefix feature or is this just not possible?
So... I've been thinking about this for a while now. - And a colleague of mine suddently showed me the light.
The problem lies where MVC maps the object to a route dictionary.
See the user
wount work. Because MVC can not handle the .(dot) in the object name.
but since the object name is just a string key in the routevaluedictionary, mapping it my self did the trick:
See the user
I am writing my first ASP.Net webpage and using MVC.
I have a string that I am building in a partial view with a grid control (DevExpress MVCxGridView). In my partial view I am using a HTML.Hidden helper as shown below.
' Create a hidden variable to pass back a comma-delimited string
Response.Write(Html.Hidden( "exclusionList", Model.ExclusionList))
The value of of this hidden element is assigned in client side javaScript:
exclusionListElement = document.getElementById("exclusionList");
// ...
exclusionString = getExclusionString();
exclusionListElement.value = exclusionString;
This seems to work without problem.
In my controller action method:
<AcceptVerbs( HttpVerbs.Post )> _
Public Function MyPartialCallback(updatedItemList As myModel) As ActionResult
Dim myData As myModel = GetMyModel()
Return PartialView( "MyPartial", myModel.myList )
End Function
The updatedItemList parameter is always nothing and exclusion list exists no where in the Request.Forms.
My questions are:
What is the correct way to use Html.Hidden so that I can access data in a MVC Controller Action method.
Is adding "cargo" variables to Request.Form the best and only way to send data back to a server side MVC Controller Action method? It just seems like twine and duct-tape approach. Is there a more structured approach?
If you need to get the exclusionList variable back, you just need to add a property to your view model that matches that name exactly. Make sure it is of the correct type (string it looks like in this case) and then it should auto populate that property in the view model for you.
And yes, there is no need for the Response.Write call. Instead just use the Html.HiddenFor(...) helper in your view.
Look at the generated HTML. Note down the name attribute of the hidden field. Use this name as action parameter name:
Public Function MyPartialCallback(exclusionList As string)
url : /jobs/UpdateJobResults/GUIDHERE
When I do a post to the below function the guid id is always blank, can I use the above format to POST the GUID in the url (as the form body has the results dictionary) ?
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateJobResults(Guid Id, Dictionary<string, object> results)
{
}
You can try revising your Html.BeginForm by passing this as a route value...
Html.BeginForm("myAction", "myController", new { Id = myGuid });
Obviously where myGuid is your param.
If your routing is setup correctly, MVC will know to post your form with this value in the URL (and/or querystring) rather than in the Request.Form data...
Good luck!
I believe that MVC uses Convert.ChangeType for conversions. This method does not support Guids. My recommendation would be to change the parameter to a string and convert it in the method.
Yes, the 3rd parameter of the default route is id. In most of the examples that is an integer, but a Guid should work.
Did you try it with the id parameter as a string instead of a Guid? Normally MVC is smart enough to give you the type of object you're looking for, but I haven't tried it with a Guid. Expecting id to be a string might work. Then at least you'd know your routing was working.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateJobResults(string id, Dictionary<string, object> results)
{
}
Are you using the default route or have you set up your own routes?
Edit: So, you're using your own routes. Please edit your question to include those. Also, you say it works for the GET, but not for the POST. What does your action look like that is hit with the GET request? I think we're going to need more information in order to help with this one. Are you sure the client requests contain the Guid in the url?
ended up being the model binder created was looking in the form for the guid on the post rather than the query string