Controller
ASP.NET MVC invokes different controller classes (and different action methods within them) depending on the incoming URL. The default mapping logic used by ASP.NET MVC uses a format like this to determine what code to invoke:
/[Controller]/[ActionName]/[Parameters]
The method named Index
is the default method that will be called on a controller if URL is not explicitly specified Action Name.
If We have an Action in Controller like this.
public string Welcome(string name, int numTimes = 1) { return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes); }
The example URL (http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numtimes=4). You can try different values for name
and numtimes
in the URL. The system automatically maps the named parameters from the query string in the address bar to parameters in your method.
You'll create a view template file using the new Razor view engine introduced with ASP.NET MVC 3. Razor-based view templates have a .cshtml file extension, and provide an elegant way to create HTML output using C#. Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow.
(See also : http://msdn.microsoft.com/en-us/vs2010trainingcourse_aspnetmvc3razor_topic2 Razor)
(See also : http://www.asp.net/mvc/videos tutorial video about Razor)
(See also: http://rachelappel.com/razor/introducing-mvc-development-w-the-razor-view-engine-for-visual-studio-developers/ Razor)
(See also: http://midnightprogrammer.net/post/RAZOR-View-Engine-In-ASPNET-MVC-3.aspx Razor)
Layout Templetes
You can create multiple Layout pages and use it in differnt views. You may mention the new layout pages inside your views by mentioning the Layout property in your views.
Create a new View
and name it as _AdminLayout.cshtml
under Views/Shared
folder. You may create your HTML markup for your master page template there. Make sure you have @RenderBody()
section in your Layout page so that the content of your normal views will be replaced here when it renders.
<html> <head> </head> <body> <h1>MynewLayout</h1> @RenderBody() </body> </html>
And if you want to use this Layout in a view, you can do it like this
@{ Layout="~/Views/Shared/_AdminLayout.cshtml"; } <p>The content here will be present inside the render body section of layout</p>
If you want to use the new Layout for all the Views by default without explicitly mentioning like the above code, you can do it in the Views/_ViewStart.cshtml
file
@{
Layout="~/Views/Shared/_AdminLayout.cshtml";
}
Passing data between view and controller
1.You can do this by having the controller put the dynamic data that the view template needs in a ViewBag
object that the view template can then access.
@{ ViewBag.Title = "Welcome"; } <h2>Welcome</h2> <ul> @for (int i=0; i < ViewBag.NumTimes; i++) { <li>@ViewBag.Message</li> } </ul>
You saw how a controller can pass data or objects to a view template using the ViewBag
object. The ViewBag
is a dynamic object that provides a convenient late-bound way to pass information to a view.
The following listing shows the HttpPost
version of the Edit
action method.
[HttpPost] public ActionResult Edit(Movie movie) { if (ModelState.IsValid) { db.Entry(movie).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }
The ASP.NET framework model binder takes the posted form values and creates a Movie
object (this is done automatically) that's passed as the movie
parameter. The ModelState.IsValid
check in the code verifies that the data submitted in the form can be used to modify a Movie
object. If the data is valid, the code saves the movie data to the Movies
collection of theMovieDBContext
instance. The code then saves the new movie data to the database by calling the SaveChanges
method of MovieDBContext
, which persists changes to the database. After saving the data, the code redirects the user to theIndex
action method of the MoviesController
class, which causes the updated movie to be displayed in the listing of movies.
Remember , even there is no method decorated with HttpPost attribute . the submit action will be directed to the default HttpGet Method.
see the code debugger fellowing. the HttpPost method is commented.
So even you add post form when creating your searchIndex view like this.
@model IEnumerable<TestMvc4App.Models.Movie> @{ ViewBag.Title = "SearchIndex"; } <h2>SearchIndex</h2> <p> @Html.ActionLink("Create New", "Create") @using (Html.BeginForm()){ <p> Title: @Html.TextBox("SearchString") <input type="submit" value="Filter" /></p> } </p> ....
And there's no HttpPost
overload of the SearchIndex
method. You don't need it, because the method isn't changing the state of the application, just filtering data.
public ActionResult SearchIndex(string searchString) { var movies = from m in db.Movies select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s => s.Title.Contains(searchString)); } return View(movies); }
Entity Framework code first migration and DB initialize
using System; using System.Collections.Generic; using System.Data.Entity; namespace MvcMovie.Models { public class MovieInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext> { protected override void Seed(MovieDBContext context) { var movies = new List<Movie> { new Movie { Title = "When Harry Met Sally", ReleaseDate=DateTime.Parse("1989-1-11"), Genre="Romantic Comedy", Rating="R", Price=7.99M}, new Movie { Title = "Ghostbusters ", ReleaseDate=DateTime.Parse("1984-3-13"), Genre="Comedy", Rating="R", Price=8.99M}, new Movie { Title = "Ghostbusters 2", ReleaseDate=DateTime.Parse("1986-2-23"), Genre="Comedy", Rating="R", Price=9.99M}, new Movie { Title = "Rio Bravo", ReleaseDate=DateTime.Parse("1959-4-15"), Genre="Western", Rating="R", Price=3.99M}, }; movies.ForEach(d => context.Movies.Add(d)); } } }
Wire this class up each time when app start.
protected void Application_Start() { Database.SetInitializer<MovieDBContext>(new MovieInitializer()); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
Validation in UI
[HttpPost] public ActionResult Create(Movie movie) { if (ModelState.IsValid) { db.Movies.Add(movie); db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }
The first action method displays the initial Create form. The second handles the form post. The second Create
method calls ModelState.IsValid
to check whether the movie has any validation errors. Calling this method evaluates any validation attributes that have been applied to the object. If the object has validation errors, the Create
method redisplays the form. If there are no errors, the method saves the new movie in the database.
Below is the Create.cshtml view template that you scaffolded earlier in the tutorial. It's used by the action methods shown above both to display the initial form and to redisplay it in the event of an error.
@model MvcMovie.Models.Movie @{ ViewBag.Title = "Create"; } <h2> Create</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true) <fieldset> <legend>Movie</legend> <div class="editor-label"> @Html.LabelFor(model => model.Title) </div> <div class="editor-field"> @Html.EditorFor(model => model.Title) @Html.ValidationMessageFor(model => model.Title) </div> <div class="editor-label"> @Html.LabelFor(model => model.ReleaseDate) </div> <div class="editor-field"> @Html.EditorFor(model => model.ReleaseDate) @Html.ValidationMessageFor(model => model.ReleaseDate) </div> <div class="editor-label"> @Html.LabelFor(model => model.Genre) </div> <div class="editor-field"> @Html.EditorFor(model => model.Genre) @Html.ValidationMessageFor(model => model.Genre) </div> <div class="editor-label"> @Html.LabelFor(model => model.Price) </div> <div class="editor-field"> @Html.EditorFor(model => model.Price) @Html.ValidationMessageFor(model => model.Price) </div> <div class="editor-label"> @Html.LabelFor(model => model.Rating) </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>
Notice how the code uses an Html.EditorFor
helper to output the <input>
element for each Movie
property. Next to this helper is a call to the Html.ValidationMessageFor
helper method. These two helper methods work with the model object that's passed by the controller to the view (in this case, a Movie
object). They automatically look for validation attributes specified on the model and display error messages as appropriate.
The validation rules and the error strings are specified only in the Movie
class.
using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations; namespace MvcMovie.Models { public class Movie { public int ID { get; set; } [Required(ErrorMessage = "Title is required")] public string Title { get; set; } [Required(ErrorMessage = "Date is required")] public DateTime ReleaseDate { get; set; } [Required(ErrorMessage = "Genre must be specified")] public string Genre { get; set; } [Required(ErrorMessage = "Price Required")] [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } }
See also:
http://www.cnblogs.com/firstcsharp/archive/2011/11/30/2268528.html
http://www.cnblogs.com/imihiroblog/archive/2012/07/08/2581248.html
http://www.asp.net/mvc/tutorials/older-versions/views/creating-custom-html-helpers-cs
http://blog.csdn.net/zgjsczwj/article/details/7698184(html helper)
http://msdn.microsoft.com/en-us/library/dd394711.aspx(passing data and validate message)
http://msdn.microsoft.com/en-us/library/ee256141.aspx (validate)
http://www.asp.net/mvc/tutorials/views/introduction-to-razor-syntax (razor syntax)
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx(mvc route tools)
http://cnn237111.blog.51cto.com/2359144/548518(map route)
http://www.cnblogs.com/chsword/archive/2008/03/12/1102206.html(filter)
http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx(@model keyword in Razor)
http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx(layout.cshtml, @url.content)
http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx(Layouts and Sections with Razor)
http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx