asp.net MVC4 Introductory tutorial (vi): Validating editing methods and editing views _ self-study process

Source: Internet
Author: User
Tags form post html form html tags http post actionlink

In this section, you will begin to modify the action methods and views that are added to the movie controller. Then, you will add a custom search page.

Add/movies to the browser's address bar and browse to the Movies page. and enter the edit page.

The edit link is generated by the Html.ActionLink method in the views\movies\index.cshtml view:

@Html. ActionLink ("edit", "edit", new {id=item.id})

An HTML object is a helper, in the form of a property, that is exposed on the System.Web.Mvc.WebViewPage base class. ActionLink is a help method for dynamically generating HTML hyperlink links that point to action methods in controller. The first parameter of the ActionLink method is the text of the link you want to render (for example, <a>edit me</a>). The second parameter is the name of the action method to invoke. The last parameter is an anonymous object that is used to generate the routing data (in this case, the ID is 4).

The link generated in the previous illustration is the URL used by the default route (set in app_start\routeconfig.cs ) HTTP://LOCALHOST:XXXXX/MOVIES/EDIT/4 Match mode is: {controller}/{action}/{id}. As a result, ASP.net converts http://localhost:xxxxx/Movies/Edit/4 to the Movies controller's Edit action method, with a parameter ID equal to 4 of the request. View the following code in the app_start\routeconfig.cs file.

public static void RegisterRoutes (RouteCollection routes)
{
   routes. Ignoreroute ("{resource}.axd/{*pathinfo}");


   Routes. Maproute (
     name: "Default",
     URL: "{controller}/{action}/{id}",
     defaults:new {controller = "Home", action = "Index", 
       id = urlparameter.optional}
   );

You can also use QueryString to pass arguments to an action method. For example, URL: http://localhost:xxxxx/Movies/Edit?ID=4 also passes a request with a parameter ID of 4 to the Edit action method of the Movies controller.

Open the Movies controller. The two edit action methods shown below.



//Get:/MOVIES/EDIT/5 public



actionresult Edit (int id = 0)

{
   Movie Movie = db. Movies.find (ID);
   if (movie = = null)
   {return
     httpnotfound ();
   }
   return View (movie);

}

//POST:/MOVIES/EDIT/5



[httppost] public

actionresult Edit (Movie Movie)

{
   if ( Modelstate.isvalid)
   {
     db. Entry (Movie). state = entitystate.modified;
     Db. SaveChanges ();
     Return redirecttoaction ("Index");
   }
   return View (movie);

}

Note that the second edit action method has the HttpPost property above it. This property specifies the overload of the Edit method, which is only invoked by the POST request. You can apply the HttpGet attribute to the first editing method, but this is not necessary because it is the default property. (The action method is implicitly specified as the HttpGet property, which is used as the HttpGet method.) )

The HttpGet Edit method gets the movie ID parameter, finds the movie using the Find method of the entity Framework, and returns to the edited view of the selected movie. If you call the Edit method without parameters, the ID parameter is specified as the default value of 0. If a movie is not found, return httpnotfound. When vs automatically creates an edit view, it looks at the movie class and creates elements for render <label> and <input> for each property of the class. The following example is an automatically created edit view:

@model MvcMovie.Models.Movie @{viewbag.title = "Edit";
     }  

Note that the view template has a @model MvcMovie.Models.Movie declaration at the top of the file, which specifies that the model type expected by the view is Movie.

Automatically generated code that uses several simplified HTML tags for the helper method. Html.labelfor is used to display the name of the field (title, ReleaseDate, genre, or price). Html.editorfor is used to render HTML <input> elements. Html.validationmessagefor is used to display any validation messages associated with this property.

Run the application, and then browse the url,/movies. Click the edit link. View the page source code in the browser. The elements in the HTML form are as follows:

<form action= "/MOVIES/EDIT/4" method= "POST" > <fieldset> <legend>Movie</legend> <i Nput data-val= "true" data-val-number= "the field ID must be a number." Data-val-required= "The ID field is required." Id= "id "Name=" ID "type=" hidden "value=" 4 "/> <div class=" Editor-label "> <label for=" Title ">title&lt ;/label> </div> <div class= "Editor-field" > <input class= "text-box single-line" id= "titl  E "name=" title "type=" text "value=" Rio Bravo "/> <span class=" field-validation-valid "data-valmsg-for=" title " Data-valmsg-replace= "true" ></span> </div> <div class= "Editor-label" > <label fo R= "ReleaseDate" >ReleaseDate</label> </div> <div class= "Editor-field" > <input clas s= "Text-box single-line" data-val= "true" data-val-date= "the field releasedate must be a date." Data-val-required= "Rel Easedate field is requireD. "Id=" ReleaseDate "name=" ReleaseDate "type=" text "value=" 4/15/1959 12:00:00 AM "/> <span class=" Field-valid Ation-valid "data-valmsg-for=" ReleaseDate "data-valmsg-replace=" true "></span> </div> <div cl ass= "Editor-label" > <label for= "Genre" >Genre</label> </div> <div class= "Editor-fi" Eld "> <input class=" text-box single-line "id=" genre "name=" genre "type=" text "value=" Western "/> &L T;span class= "field-validation-valid" data-valmsg-for= "Genre" data-valmsg-replace= "true" ></span> </div > <div class= "Editor-label" > <label for= "Price" >Price</label> </div> &L T;div class= "Editor-field" > <input class= "Text-box" Single-line "true" data-val= "the field Pr Ice must be a number. "Data-val-required=", the Price field was required. "Id=" Price "name=" Price "type=" text "value=" 2.99 "/ > <span class="Field-validation-valid" data-valmsg-for= "Price" data-valmsg-replace= "true" ></span> </div> < P> <input type= "Submit" value= "Save"/> </p> </fieldset> </form>

The <input> elements that are included in the <form> HTML element are sent to the Url:/movies/edit set by the action attribute of the form. When you click the Edit button, the from data is sent to the server.

Process POST Requests

The following code shows the HttpPost processing 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 MVC model binds to receive the data that is post by Form and transforms the received movie request data to create a movie object. The Modelstate.isvalid method is used to verify that the submitted form data can be used to modify (edit or update) a movie object. If the data is a valid movie data, it is saved to the Movies collection (Moviedbcontext instance) of the database. By invoking the Moviedbcontext SaveChanges method, new movie data is saved to the database. After the data is saved, the code redirects the user to the index action method of the Moviescontroller class, and the page displays a list of movies, including the updates that were just made.

If the form sends a value that is not a valid value, they will be displayed again in the form. The Html.validationmessagefor helper in the edit.cshtml view template will be used to display the appropriate error message.

Note that in order for jquery to support non-English domain validation using commas, you need to set a comma (",") to represent the decimal point, you need to introduce globalize.js and you need to specify the specific cultures/ Globalize.cultures.js files (addresses in https://github.com/jquery/globalize) can use Globalize.parsefloat in JavaScript. The following code shows the views\movies\edit.cshtml view under the "FR-FR" culture:

@section Scripts {
   @Scripts. Render ("~/bundles/jqueryval")
   <script src= "~/scripts/globalize.js" >< /script>
   <script src= "~/scripts/globalize.culture.fr-fr.js" ></script>
   <script>
     $.validator.methods.number = function (value, Element) {return
       this.optional (element) | |
         ! isNaN (Globalize.parsefloat (value));
     }
     $ (document). Ready (function () {
       globalize.culture (' fr-fr ');
     });
   </script>
   <script>
     jquery.extend (jQuery.validator.methods, {  
       range:function) (value, element, param) {    
         //use the globalization plugin to parse the value    
         var val = $.global.parsefloat (value);
         return this.optional (Element) | | (
           val >= param[0] && val <= param[1]);


   </script>

}

A decimal field might require a comma, not a decimal point. As a temporary fix, you can add globalization settings to the project root Web.config file. The following code shows the global cultural setting set for American English.

<system.web>
   <globalization Culture = "en-Us"/>
   <!--elements removed for clarity-->
</system.web>

All HttpGet methods follow a similar pattern. They get the movie object (or collection of objects, such as the collection of objects in index) and pass the model to the view. The Create method passes an empty movie object to the creation view. The way to create, edit, delete, or otherwise modify data is the HttpPost method. Using the HTTP GET method to modify data is a security risk and is fully described in the ASP.net MVC Tip #46 –don ' t use Delete Links because they the blog create security holes. Modifying the data in the Get method also violates the HTTP best practices and Rest schema mode, and the GET request should not change the state of the application. In other words, performing a get operation should be a safe operation without any side effects and will not modify the data that you persist.

Add a search method and search view

In this section, you will add a Searchindex action method that searches for the genre or name of the movie. This will be available using the /movies/searchindex URL. The request displays an HTML form containing the input elements that the user can enter into a movie to search for. When a user submits a form, the action method gets the search criteria entered by the user and searches the database.

Show Searchindex Form

Start by adding the Searchindex action method to the existing Moviescontroller class. This method returns a view containing an HTML form. The following code:

Public ActionResult Searchindex (string searchstring) 

{      
   var movies = out m in db. Movies 
         Select m; 
 
   if (! String.IsNullOrEmpty (searchstring)) 
   { 
     movies = movies. Where (S => s.title.contains (searchstring)); 
   } 
 
   Return View (Movies); 

}

The first line of the Searchindex method creates the following LINQ query to choose to see a movie:

var movies = from M in db. Movies 
         Select M;

The query at this point is just defined and has not yet been executed on the data.

If the SearchString parameter contains a string, you can modify the search string that the movie query will filter by using the following code:

if (! String.IsNullOrEmpty (searchstring)) 
{ 
  movies = movies. Where (S => s.title.contains (searchstring)); 
}

The above S-=> s.title code is a lambda expression. A LAMBDA is a method based LINQ query, (for example, the where query above) uses the standard query parameter operator method in the preceding code. LINQ queries are not executed when a LINQ query is defined or when a query condition is modified, such as when a where or an by method is invoked. Instead, query execution is deferred, which means that the expression is computationally delayed until the actual value is obtained or the ToList method is invoked. In the Searchindex example, the query is executed in the Searchindex view. For more information about deferred query execution, see query Execution.

You can now implement the Searchindex view and display it to the user. Right-click inside the Searchindex method, and then click Add View. In the Add View dialog box, specify that you want to pass the movie object to the view template as its model class. In the list of frame templates, select the list, and then click Add.

When you click the Add button, the views\movies\searchindex.cshtml view template is created. Because you have selected a list of frame templates, Visual Studio will automatically generate some of the default tags in the list view. The framework template creates an HTML form. It examines the movie class and creates a <label> element for each property of the class to be displayed. The following is the generated view:

@model ienumerable<mvcmovie.models.movie> @{viewbag.title = "Searchindex"; }  

Run the application, and then go to /movies/searchindex. Append query string to URL such as Searchstring=ghost. Displays the movies that have been filtered.

If you change the signature of the Searchindex method to the parameter ID, the default route set in the Global.asax file will make the: ID parameter match the {ID} placeholder.

{Controller}/{action}/{id}

The original Searchindex method looks like this:

Public ActionResult Searchindex (string searchstring) 

{      
   var movies = out m in db. Movies 
         Select m; 
 
   if (! String.IsNullOrEmpty (searchstring)) 
   { 
     movies = movies. Where (S => s.title.contains (searchstring)); 
   } 
 
   Return View (Movies); 

}

The modified Searchindex method looks like this:

Public ActionResult Searchindex (string id) 

{ 
   string searchstring = ID; 
   var movies = from M in db. Movies 
         Select m; 
 
   if (! String.IsNullOrEmpty (searchstring)) 
   { 
     movies = movies. Where (S => s.title.contains (searchstring)); 
   } 
 
   Return View (Movies); 

}

You can now replace QueryString with the search headers as routing data (partial URLs).

However, every time a user wants to search for a movie, you can't expect the user to modify the URL. So, now you're going to add UI pages to help them filter the movie. If you change the Searchindex method to test how to pass the ID parameter of a routing binding, change it so that your Searchindex method takes a string searchstring parameter:

Public ActionResult Searchindex (string searchstring) 

{      
   var movies = out m in db. Movies 
          Select m; 
 
   if (! String.IsNullOrEmpty (searchstring)) 
   { 
     movies = movies. Where (S => s.title.contains (searchstring)); 
   } 
 
   Return View (Movies); 

}

Open the views\movies\searchindex.cshtml file, and after @Html. ActionLink ("Create New"), add the following:

@using (Html.BeginForm ()) {  
  <p> Title: @Html. TextBox ("searchstring") <br/> 
  <input type= " Submit "value=" Filter "/></p> 
}

The following example shows a portion of the views\movies\searchindex.cshtml file after adding:

@model ienumerable<mvcmovie.models.movie> 
 

@{ 
   viewbag.title = "Searchindex"; 

} 
 

 
 

Html.BeginForm Helper creates open <form> tag. The Html.BeginForm helper will make the form post this URL when the user submits the form by clicking the Filter button. To run the application, try searching for a movie.

Searchindex There is no HttpPost overload method. You don't need it because the method does not change the state of the application data, it just filters the data.

You can add the following HttpPost Searchindex method. In this case, the request enters the HttpPost Searchindex method, HttpPost The Searchindex method returns the contents of the following figure.

[HttpPost] 

public string Searchindex (FormCollection FC, string searchstring) 

{return 
   '  
 

However, even if you add this HttpPost Searchindex method, this implementation is actually limited. Imagine that you want to bookmark a specific search, or you want to send a search link to a friend, and they can click to see the same movie search list. Note that the URL of the HTTP POST request and the URL of the GET request are the same (localhost:xxxxx/movie/searchindex)--There is no search information in the URL. The search string information is now sent to the server as the form field value. This means that you cannot capture this search information in a URL to add a bookmark or send it to a friend.

The workaround is to use overloaded beginform, which specifies that the POST request should be added to the URL's search information and should be routed to the HttpGet Searchindex method. Modify the existing parameterless BeginForm method to the following:

@using (Html.BeginForm ("Searchindex", "Movies", Formmethod.get))

Now when you submit the search, the URL will contain the query string for the search. The search also requests the HttpGet Searchindex action method, even if you have a HttpPost Searchindex method.

Add search by movie genre

If you added a HttpPost searchindex method, delete it now.

Next, you'll add features to let users search for movies by genre. Replace the Searchindex method with the following code:

Public ActionResult Searchindex (string moviegenre, string searchstring) 

{ 
   var genrelst = new list<string> (); 
 
   var genreqry = from D in Db. Movies by 
          d.genre 
          Select D.genre; 
   Genrelst.addrange (Genreqry.distinct ()); 
   Viewbag.moviegenre = new SelectList (GENRELST); 
 
   var movies = from M in db. Movies 
         Select m; 
 
   if (! String.IsNullOrEmpty (searchstring)) 
   { 
     movies = movies. Where (S => s.title.contains (searchstring)); 
   } 
 
   if (string. IsNullOrEmpty (moviegenre)) return 
     View (Movies); 
   else 
   {return 
     View (Movies). Where (x => x.genre = = moviegenre)); 
   } 
 

This version of the Searchindex method will accept an additional moviegenre parameter. The first few lines of code create a list object to hold the movie genre in the database.

The following code is a LINQ query that retrieves all genres from the database.

var genreqry = from D in Db. Movies by 
          d.genre 
          Select D.genre;

The code adds all the different genres to the collection using the AddRange method of the generic list collection. (with the distinct modifier, no repeating genre is added--for example, two comedies were added to our example.) The code then stores the genre's list of data in the ViewBag object.

The following code shows how to check the Moviegenre parameter. If it is not empty, the code further specifies the genre of the movie being queried.

if (string. IsNullOrEmpty (moviegenre)) return 
  View (Movies); 
else 
{return 
  View (Movies). Where (x => x.genre = = moviegenre)); 
}

Add a selection box to the Searchindex view support by genre search

Add the Html.dropdownlist helper to the views\movies\searchindex.cshtml file before the TextBox helper. After the addition is complete, as shown in the following:

<p> 
   @Html. ActionLink ("Create New", "create") 
   @using (Html.BeginForm ("Searchindex", "Movies"), Formmethod.get)) {   
     <p>genre: @Html. DropDownList ("Moviegenre", "All")  
      Title: @Html. TextBox (" SearchString ")  
     <input type=" Submit "value=" Filter "/></p> 
     } 

</p>

Run the application and browse the /movies/searchindex. Try the search by genre, by movie name, or both.

In this section, you modify the views generated by the CRUD operations methods and frameworks. You create a search action method and view that allows users to search for movie titles and genres. In the next section, you will see how to add a property to the movie model and how to add an initial setting and automatically create a test database.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.