C# ASP.NET MVC: Dynamic Querystring for Search - c#

I have the following scenario:
1) A phone book table
2) Multiple ways of searching through the table (first name, last name)
3) There is also the obligatory paging (page size and page number) as well as sorting
When the user accesses the page first the Url is simply /Phonebook. Now let's say the user is searching for "abc", then the Url becomes /Phonebook?q=abc. Then he is sorting ascending by first name, and the Url should become /Phonebook?q=abc&sort=firstName&order=asc.
The problem I have is how do I program my view to automatically append/modify the query string so that it still contains previously entered constraints (as in my "abc") query but adjusts/adds new constraints for example if sorting, and then paging etc. is used?
I'd hate to use JS and rewriting the location for this, and rather have the page generate real anchors (a href) after every postback for each sort/page/filter link on my page.
Appreciate your time folks :)

I assume you have some sort of controls on the page to set what will be sorted, in what order and obviously a way to define what will filtered?
When you load the page, why not set those values in the view and then the controller should update correctly on the next load? That way it is easy for the user to change them as well without needing to touch the URL. In this case it is straight forward passing the data from the controller to the view and setting the values as you would any other control, for instance:
<input type="text" name="search" value="<%= (string)ViewData["Search"] %>" />
If you really need it in the URL, you can modify the button by passing the extra parameters in an anonymous type.
For a link something like this:
<%= Url.Action("Search", "PhoneBook", new {order="asc"}) %>
For a form (since you don't specifically set a submit button) something like this
<% using (Html.BeginForm(new {order="asc"}) {
You could pull those from the controller by doing something like
<% using (Html.BeginForm(new { sort=(string)ViewData["Sort Order"] }))

Just pass extra parameters in with an anonymous object:
<%= Html.ActionLink("Sort ascending", "Search", "PhoneBook", new {order="asc"}) %>
<!-- or -->
<%= Url.Action("Search", "PhoneBook", new {order="asc"}) %>
If the extra parameters are not defined in the route, they will be added as query strings.

Related

How can I respond to events on a page in an ASP.NET MVC app that need to access data within the View?

In my ASP.NET MVC project, I need to dynamically manipulate some html elements when the user makes a couple of selections. I assume this needs to be done in code-behind C# (as opposed to in jquery), because how I respond is using data that is retrieved from a SQL Server database and is part of the View (I don't think jQuery would/could know about this MVC/.NET-specific data).
Specifically, when a user clicks a checkbox on the page, provided a selection has been made from an html-select element, my code needs to spring into action to populate other elements on the page.
The View (.cshtml) is getting the data in a Razor code block like so:
#model WebAppRptScheduler.Models.HomeModel
#using System.Data
#{
DataTable dtUnitReportPairEmailVals = Model.UnitReportPairEmailVals DataTable;
var unitRptPairEmailVals = from x in dtUnitReportPairEmailVals.AsEnumerable()
select new
{
emailAddr = x.Field<string>("EmailAddr")
};
This data comes from the Controller:
DataTable UnitReportPairEmailValsDT = new DataTable();
UnitReportPairEmailValsDT = SQL.ExecuteSQLReturnDataTable(SQL.UnitReportPairEmailQuery, CommandType.Text, null);
model.UnitReportPairEmailVals = UnitReportPairEmailValsDT;
Does this (event handling) code belong in the Controller? If so, how is the method declared/decorated so that there is a connection between it and the html elements whose events it needs to monitor?
This is what needs to happen:
User selects an option from an html select
User clicks a checkbox
The code determines that both an option has been selected, and a checkbox checked; it then uses the data to populate other controls, something like this:
#if (unitRptPairEmailVals.Count > 0)
{
email1.Text = unitRptPairEmailVals[0];
}
#if (unitRptPairEmailVals.Count > 1)
{
email2.Text = unitRptPairEmailVals[1];
}
#if (unitRptPairEmailVals.Count > 2)
{
email3.Text = unitRptPairEmailVals[2];
}
The above would populate the text/value of these html inputs:
<label class="margin4horizontal">Email 1</label><input type="text" name="email1" id="email1" />
<label class="margin4horizontal">Email 2</label><input type="text" name="email2" id="email2" />
<label class="margin4horizontal">Email 3</label><input type="text" name="email3" id="email3" />
BTW, if I'm barking up the wrong tree, or am even in the wrong forest altogether, please let me know what the preferred approach is.
UPDATE
Once I pieced together several different answers to this and related questions, I wrote up a tip on how to do this here.
Update: I was answering on mobile last night, and here is a clearer edit and some sample code...
Asp.net MVC has controllers, which contain actions. When you navigation to a URL (HTTP GET), ASP.net translates this via routes into a specific controller action to invoke, then the result of that action is sent back to the browser as plain HTML.
Also when you submit a form (HTTP POST) to specific URL it translates to invoking a controller action via routes. and a ModelBinder will read the body of that HTTP POST and converts it into your Model class. Unlike the classic web forms that used ViewState to track page controls, state, and events.
What you want to achieve can be done in 2 different ways...
Using JavaScript and JQuery. You can issue an Ajax request (GET, POST, etc) to a URL that exists in your ASP.net MVC routes table to execute an action and the results will be returned back to your JavaScript without navigating to another page.
Posting an HTML Form back to the server will allow ASP.net MVC to read the new/changed values in your HTML controls and pass those new values to the controller action, which in turn can render the same view again with the new values and behaviour.

Pass Value from View to Controller - MVC

i have a list of thumbnails for the user can select one of the image.
onclick on the thumbnail open a larger image into a form.
What im trying to do now is send the id of the image selected to my controller.
Note: im using MVC 4.
how can i do that?
someone can help with this pls?
Thanks in advance:
Here is my code:
#foreach (var p in ViewBag.Images)
{
<li>
<a href="~/Files/#p.Name" onclick="swap(this); return false;">
<img src="~/Files/#p.Name"/>
</a>
</li>
}
when selected is going this img tag in my form:
<img id="main" src="" >
using this javascript for this event:
function swap(image) {
document.getElementById("main").src = image.href;
}
what i have to do now?
i trying with <input type="hidden" name="Img_Id" value="Viewbag.??????"/>
to pass this value to my controller??
First, some terminology help: You can't pass a value from the view to the controller action, the view is rendered after the controller action completes.
What you want to do is pass data from the client (web browser) to a controller action, using form fields.
In your javascript swap method, you could set the value of the Img_Id field to be the value for the selected image. When the form is submitted, the Img_Id will be posted as form data, and can be accepted as a parameter in the action.
You can use JQuery (or something else) to perform the client side actions.
Here's an example (not tested though!):
First add the ID as a data attribute on the element:
<a href="~/Files/#p.Name" data-id="#p.ID" onclick="swap(this); return false;">
Then some javascript to save that to form (using jquery here):
function swap(image) {
document.getElementById("main").src = image.href;
$("input[name='Img_Id']").val($(image).data("id"));
}
To pass a value back to your controller, you either need to submit a form, or else make an AJAX request to your controller.
In the first case, you'd need to update the value of your hidden field with javascript, and then either wait for the user to submit the form, or trigger a submit through javascript depending on what your needs are.
If you want to do an ajax request, it would be more or less the same thing, but you don't need a hidden field to store the value.
You could use jQuery in your swap function. See here for the official documentation.
If you chose to use this approach, and assuming you place your JavaScript in a separate file, then make sure you get the path for the action and controller and pass that in too.
var url = #Url.Action("Index","Home");
Therefore you may call: onclick="swap(this.id, url)"

Is this project doable in ASP.NET MVC?

I am new to Stack Overflow and to ASP.NET MVC.
I have been asked to do a project where I want to use ASP.NET MVC, but I have some problems wrapping my head around it and I hope some of you could get me in the right direction.
The project is a kind of a search portal. On every page there is a dropdown box where you basicly select the dataset (it's based on books) you want to search. In the dropdown is the name of the book you want to search.
Of course there is also a search field. These 2 objects are on every page and has the same function on all pages, and I can't get these 2 objects to communicate.
I have these 2 in separate partialviews and want to generate an action for the search formfield something like this:
domain.com/{bookname}/search/{searchterm}: this is the thing created from the dropdown and the search box.
But can I do this in the searchfields partialview in some way, or do I have to grab these value in each controller?
I hope this makes any sense.
Create a partial view with your dropdown and textbox, using the BeginForm helper:
<% using(Html.BeginForm("Index", "Search")) %>
<% { %>
<%= Html.DropDownList("BookNames") %>
<%= Html.TextBox("SearchTerm") %>
<% } %>
Then in your SearchController's Index action, you should be able to grab the values from the form collection or using your dropdown's and textbox's id.
public ActionResult Index(FormCollection frmCollection)
{
// ...
// also you can redirect to another action/controller if you needed
// return RedirectToAction("...", "...");
}
or
public ActionResult Index(int bookNames, string searchTerm)
{
// ...
// also you can redirect to another action/controller if you needed
// return RedirectToAction("...", "...");
}
Hope this helps.
I have implemented a similar search requirement on one of my projects with ASP.NET MVC. However, I had the Dropdown and Search in a single Partial View.
I then used Javascript to pick up the selected values and redirect the user to the URL with pattern domain.com/{criteria}/search/{searchWord}.
This way I had to use a single controller to search, with a single view to view search results.

ASP.NET MVC 2.0: Simple Model Binding not working/binding as it should

ASP.NET MVC 2.0: Simple Model Binding not working/binding as it should
i have a simple custom object names Comment (linq to sql generated one), it has various values, but only two values are being sent from a HTML POST from to my action, and here is my action that accepts them...
Function InsertComment(ByVal Comment As Comment) As ActionResult
' both CommentForPicID As Integer and Comment As String are the two values sent.
End Function
The textarea is named using the TextAreaFor and the hidden id with HiddenFor, and i have checked to make sure the property names of my Comment object match exactly (case and all) with the HTML ID/Name values of the FORM elements, both are CommentForPicID and Comment without any prefixes.
i have a breakpoint on my action to see whats going on, When my action receives it, the Comment object is always set to Nothing, throughout the action, and eventually an exception is thrown as i'm trying to use a null object.
i have read steven sandersons MVC framework's model binding section, everything should be in order, does anyone have any ideas?
.
.
.
Additional information (reading not required):
however the interesting thing is, if i wrap the Comment object up in a parent object, say, CommentsParent with contains some stuff & the Comment object as variables... then i of course change the form elements id's with the apporpriate prefixes, it then works as prescribed... but i did this just to test that binding was working, and dont want/need to do this for my application.
here is the markup for anyone who wants to see it:
<%# Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of FP.Comment)" %>
<%# Import Namespace="FP" %>
<%--The line below is a workaround for a VB / ASPX designer bug--%>
<%=""%>
<% Html.EnableClientValidation()%>
<% Using Ajax.BeginForm("InsertComment", "Home", New AjaxOptions With {.UpdateTargetId = "InsertComment", .HttpMethod = FormMethod.Post})%>
<%= Html.HiddenFor(Function(x) x.CommentForPicID)%>
<%= Html.TextAreaFor(Function(x) x.Comment, 8, 40, New With {.style = "overflow: hidden;"})%><br />
<%= Html.ValidationMessageFor(Function(x) x.Comment)%>
<input type="submit" value="Save" name="SaveCancelButton"/>
<input type="submit" value="Cancel" name="SaveCancelButton" />
<% End Using %>
The problem is that your model class is named Comment and inside you have a string property also called Comment that you try to bind to the textarea. This doesn't work as the binder is getting confused. Either use a bind prefix or rename the property or the class so that they are different.

Put current route values/url in form post

In my master page, I have a language dropdown menu. When the user selects a language from the dropdown, a submit sends the currently selected language to the "Translate" method in my controller. After which it should redirect to the url it was before the translation submit so it can show the exact same page, but now in the newly selected language.
How would I best go about this? Should I send the current url somehow in a hidden field? Or can I maybe send the current routevaluedictionary, so my translate method can redirectToRoute directly?
Or maybe there is an entirely better way?
--EDIT--
Because I want my bookmarks to include the site language too, all my exposed actions have a siteLanguage parameter too. If I could somehow efficiently show the user a bunch of regular (GET) links where the siteLanguage parameter is filled in with the relevant value, that would be even better. But as far as I know, there is no way to put links in a dropdown except with java maybe.
I have a similar situation, and I solved it slightly differently.
Because my master page had functionality in it, I created a new base controller class (that inherits from Controller) and all my real controllers inherit from my custom class.
Then, I implement OnActionExecuting in the base class to do some common work.
Then, in your masterpage, if you have a form like this, it will submit to the current URL with a GET request and add the language as a querystring parameter:
<form id="language" method="get" >
<select name="language">
<option value="en">English</option>
<option value="es">Spanish</option>
...
</select>
</form>
Use jQuery to wire it up to autosubmit, etc.
You could look for a language parameter in the querystring in your base controller class and set the flag that tells the real controller method which language to use. In the model, you directly go to the real controller to regenerate the page and avoid a redirect.
Note, this only works universally, if you are not already using querystring parameters.
If this doesn't work for you, you could also use your current method, but include the URL to be redirected to in a hidden field like this:
<%= Html.Hidden("redirect", Request.Url %>
public ActionResult Translate(string _lang){
switch(_lang){
case "English":
return View("English");
case: "French":
return View("French");
default:
return View("English");
}
I would personally do it like this
I would put the return url in the querystring, just like forms authentication does when it redirects to the login page.
Include the returnUrl in the routeValues when you do your Translate request.

Categories

Resources