ASP.NET MVC 2 - Simple Search Page - asp.net

I just started ASP.NET MVC (coming from WebForms) and I'm struggling with some really basic concepts.
I want to create a single page that uses a textbox for date input. I would like the date input to be passed to the index of my controller which looks like this:
public ActionResult Index(int month,
int day,
int year){
var visitors = visitorRepoistory.FindVisitorsByDate(month, day, year).ToList();
return View("Index", visitors);
}
Up to this point I have used scaffolding with strongly typed views so everything was kind of glued together for me.
What would/should my view look like? Would I use an actionlink (this is a get request after all, right?) and not a submit button.
Thanks.

I thought about this for a while before trying to come up with an answer. What threw me initially was the concept of turning a single text input string into it's month, day, and year components. In ASP.NET MVC, it would be much easier to just accept the string for the date. This way, your code changes to:
public ActionResult Index(string date) {
try
{
DateTime dtDate = DateTime.Parse(date);
var visitors = visitorRepoistory.FindVisitorsByDate(dtDate.month,
dtDate.day, dtDate.year).ToList();
return View("Index", visitors);
}
catch (FormatException)
{
//String was not a valid date/time
}
}
Are there ways to split it up into 3 ints? I'm sure. But to me, this would be the easiest/quickest way to the goal.
So in the view, you'll have your form looking something like this:
<% using(Html.BeginForm("VisitorSearchController", "Index")) { %>
Enter a date: <%= Html.TextBox("date") %>
<input type='submit' value='Search' />
<% } %>
Where "VisitorSearchController" is the name of the controller you want to post back to. Of course, "Index" is the method you're posting to. I'd stick with the submit button for now unless you're trying to get a LinkButton equivalent on the page. But you can save the "prettying up" part after functionality, right?
Edit: Added view code to the answer.

EDIT after comment:
Simplest way is to make the search input page post (not get) back to some other method, parse the date out, then redirect to the Action you have specified.
If you want to do it through get, then you can use some Javascript trickeration to link to whatever they type in, but I recommend the former.

Related

ASP.Net - how to have multiple submit buttons and also submit the form via javascript?

I'm new to ASP.Net and am trying to make a web application using MVC2.
On one particular page I need to have multiple submit buttons - after reading up from this post I found this method which worked well in my project.
So I have a few submit buttons handled in my controller like this:
[HttpPost]
[MultiButton(Key = "action", Value = "Button1")]
public ActionResult Action1(MyViewModel myViewModel)
{ //do stuff
return View(newViewModel)
}
[HttpPost]
[MultiButton(Key = "action", Value = "Button2")]
public ActionResult Action2(MyViewModel myViewModel)
My problem is that now I want to also postback my form on various client events. I tried to do this in the view by using javascript in there somewhere.
<% using (Html.BeginForm("Index", "MyController")){ %>
document.forms["form1"].submit();
With a 'normal' action on the controller:
[HttpPost]
public ActionResult Index(MyViewModel myViewModel)
{
}
But when I add this, now the multiple submit buttons do not work properly due to an ambiguous match exception between Action1 and Index. I realise that they have the same signature but as a beginner, I'm a bit stuck at this point!
What can I do to get all the different submit options working together? Please advise and/or point out where I'm going wrong. Thanks

MVC4 Ajax forms: How to display server side validation

I am using #Ajax.BeginForm helper method, which submits form data to the server by Ajax. When the data arrive to the server, some server side validation is processed and final result is passed back to the browser.
My problem is, I want the errors to be displayed without page refresh. I have found plenty of questions based on this but they are old. I am wondering if there is some new way how to achieve this. The best way I have found so far is to process the result using jQuery. But maybe in new MVC4 there is some built in functionality how to achieve this problem in a better way?
Your view should look similar to this:
<div id="update-this">
#using (Ajax.BeginForm("YourAction", new AjaxOptions { UpdateTargetId = 'update-this' }))
{
}
</div>
Also use #Html.ValidationMessageFor(model => model.someField) next to your fields to display the error message.
On server side return a partial view if there was any error:
public ActionResult YourAction(YourModel yourmodel)
{
if (ModelState.IsValid)
{
// Do what is needed if the data is valid and return something
}
return PartialView("DisplayPartial", yourmodel);
}
And use Data Annotations on your model to make it work. (Tutorial here.)

render a string in MVC just like rendering a view, possible?

is it possible to render a string like this:
public ActionResult Do(){
s = " hello, click here <%=Html.ActionLink(\"index\",\"index\") %> ";
return Content(RenderString(s));
}
the result would something like this:
hello, click here index
What is the purpose of this? You have a controller action which tries to evaluate some string WebForms syntax string and return it as content. Why not simply return the view and have this view do the job?
If you want dynamic to have views (coming from a database or something) you could write a custom view engine and personalize their location so that your action looks like this:
public ActionResult Do()
{
return View();
}
and the corresponding view contents will be fetched from your custom view engine instead of the standard file locations.
If you want to render the contents of a view into a string this has been covered in many blog posts. Finally if you are dealing with sending views as emails there are probably better solutions.
So depending on what you are trying to achieve there might be different solutions.
public String Do(){
string s = " hello, click <a href='" + Url.Action("Index") +"' > here </a>";
return s;
}
then if you call {Controller}/Do you will have your string
EDITED
Marco

ASP.NET MVC Submitting Form Using ActionLink

I am trying to use link to submit a form using the following code:
function deleteItem(formId) {
// submit the form
$("#" + formId).submit();
}
Basically I have a grid and it displays a number of items. Each row has a delete button which deletes the item. I then fire the following function to remove the item from the grid.
function onItemDeleted(name) {
$("#" + name).remove();
}
It works fine when I use a submit button but when I use action link the JavaScript from the controller action is returned as string and not executed.
public JavaScriptResult DeleteItem(string name)
{
var isAjaxRequest = Request.IsAjaxRequest();
_stockService.Delete(name);
var script = String.Format("onItemDeleted('{0}')", name);
return JavaScript(script);
}
And here is the HTML code:
<td>
<% using (Ajax.BeginForm("DeleteItem",null, new AjaxOptions() { LoadingElementId = "divLoading", UpdateTargetId = "divDisplay" },new { id="form_"+stock.Name }))
{ %>
<%=Html.Hidden("name", stock.Name)%>
<a id="link_delete" href="#" onclick="deleteItem('form_ABC')">Delete</a>
<% } %>
</td>
My theory is that submit button does alter the response while the action link simply returns whatever is returned from the controller's action. This means when using submit the JavaScript is added to the response and then executed while in case of action link it is simply returned as string.
If that is the case how can someone use action links instead of submit buttons.
UPDATE:
Seems like I need to perform something extra to make the action link to work since it does not fire the onsubmit event.
http://www.devproconnections.com/article/aspnet22/posting-forms-the-ajax-way-in-asp-net-mvc.aspx
My guess is the MS Ajax form knows how to handle a JavaScriptResponse and execute the code whereas your plain old Action link, with no relationship to the AjaxForm, does not. I'm pretty sure the MS ajax library essentially eval()s the response when it sees the content type of javascript being sent back.
Since you have no callback in your deleteItem() method there is no place for the script to go. To fix you'll have to manually eval() the string sent back which is considered a bad practice.
Now I'm not familiar with the MS Ajax library to be certain of any of this but what your doing is possible. I'd do things differently but don't want to answer with a "my way is better" approach ( especially because your blog has helped me before ) but I'd like to show this can be easier.
I'd ditch the form entirely and use unobtrusive javascript to get the behavior you want. IN psuedo jqueryish ( don't know ms ajax ) code:
function bindMyGrid() {
$('.myDeleteLink').onclicksyntax( function() {
//find the td in the row which contains the name and get the text
var nameTdCell = this.findThisCellSibling();
//do an ajax request to your controller
ajax('myUrl/' + nameTdCell.text(), function onSuccessCallback() {
//get the tr row of the name cell and remove it
nameTdCell.parent().remove();
});
});
}
This also gains the benefit of not returning javascript from your controller which some consider breaking the MVC pattern and seperation of concerns. Hope my psuedo code helps.
Try without the UpdateTargetId property in the AjaxOptions (don't specify it)
new AjaxOptions() { LoadingElementId = "divLoading" }
What about just change look of a standard or using some css class? It'll look like a link and you'll avoid some problems you get with anchors - user will be able to click on it by a mouse wheel and open that link in a new tab/window.

ASP.NET MVC View User Control - how to set IDs?

I need a dropdown list on my page that will allow a user to select their state. Since this is probably a control that will be used elsewhere, I thought it would be a good idea to create an MVC View User Control that could be reused.
I was thinking the control would look something like this:
<select name="" id="">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
</select>
And the code in my view would be something like:
<%= Html.RenderPartial("StateDropdownControl") %>
My question is, what's the best way to set the name and id on the control? I'd want to make sure I could have multiple instances of this control on one page, if needed. Also, I'd want to be able to send in the state that should be selected by default.
Would I do it with ViewData somehow?
Corey is on to the right solution. I think declaring specific Model objects for your view makes the views VERY simple and as a side bonus makes them dirt easy to test.
So instead of just passing the ID as the object, you'd probably want to create your own Model object to pass in.
It could look something like this:
public class StateDropDownPresentationModel
{
public string DropDownID { get; set; }
public string SelectedState { get; set; }
}
Obviously, keep adding whatever you need to this model to make your view correct.
Then, you could call it like this:
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", new StateDropDownPresentationModel { DropDownID = "MyID", SelectedState = "IL" } %>
Then just make sure you put in checks for things like ID being null/blank (that should probably throw an error) and SelectedState being null/blank.
Well you can pass object data to the RenderPartial method in conjunction to the User Control to render, so you could easily do the following:
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", "MyID") %>
and in the UserControl do the following:
<select name="<%=ViewData.Model%>" id="<%=ViewData.Model%>">
....
Just to be sure, a better way to handle it is to make a simple DTO (data transfer object) to hold that information so you can pass more information to your user control, that you will inevitably need.
Example:
class ComboData
{
string ID {get;set;}
string CssClass {get;set;}
//Other stuff here
}
<%
var comboData = new ComboData {ID = "myID", CssClass = "comboStyle" }
%>
<%= Html.RenderPartial("/someDirectory/SomeControl.ascx", comboData) %>
<select name="<%=ViewData.Model.ID%>" id="<%=ViewData.Model.ID%>" class="<%=ViewData.Model.CssClass%>">
....
Make sure you set the Code behind for the user control to be a generic of type ComboData for this example.
Take a look at the Html.DropDownList helper method. It has a number of overloads that allow you to pass the list data and set the selected item. the simplest version just sets the name of the select.
<%= Html.DropDownList("SelectStates"); %>
If there is a value in the ViewData["SelectStates"] that is of type MultiSelectList then the list will be automatically populated.

Resources