MVC Tutorial Movie DIY

 

Razor cshtml

 

Razor cshtml

Razorcshtml,MVC的视图设计引擎.

 

view 目录下的 _ViewStart.cshtml

   @{

    Layout = "~/Views/Shared/_Layout.cshtml";

}

指定模板页 (即把_Layout.cshtml作为母页)

 

 

sample列表

>MovieStore

http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model

 

(3)index.cshtml  (显示列表的Razor)

>This @model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed

       (model就是Controller传个Razor页的Movie对象)

 

@model IEnumerable<MvcMovie.Models.MoviesModel>

 

@{

    ViewBag.Title = "Index";

}

 

<h2>Movies List</h2>

 

<p>

    @Html.ActionLink("Create New", "Create")

</p>

<table>

    <tr>

        <th>

            @Html.DisplayNameFor(model => model.Price)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.Title)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.RealeaseDate)

        </th>

        <th></th>

    </tr>

 

@foreach (var item in Model) {

    <tr>

        <td>

            @Html.DisplayFor(modelItem => item.Price)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.Title)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.RealeaseDate)

        </td>

        <td>

            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |

            @Html.ActionLink("Details", "Details", new { id=item.ID }) |

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

        </td>

    </tr>

}

 

</table>

 

@model IEnumearable<>

IEnumerable <类名>

       枚举器,类似于集合。 使用 foreach(var item in ) 来遍历

 

(5)index.cshtml Detail.cshtml比较

index.cshtml    @model IEnumerable<MvcMovie.Models.MoviesModel>

detail.cshtml    @model MvcMovie.Models.MoviesModel

 

index接收的是db.Movies.ToList();

detail接收的db.Movies.Find(id)

 

 Html.DisplayFor Html.ActionLink

// Html.ActionLink  根据controller传的值动态生成链接地址

 

@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |

1链接名  2)调用Controller中的哪个Action (3)route data

       The first argument to the ActionLink method is the link text to render (for example, <a>Edit Me</a>). The second argument is the name of the action method to invoke. The final argument is an anonymous object that generates the route data (in this case, the ID of 4).

The generated link shown in the previous image is http://localhost:xxxxx/Movies/Edit/4. The default route (established in Global.asax.cs) takes the URL pattern {controller}/{action}/{id}. Therefore, ASP.NET translates http://localhost:xxxxx/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter ID equal to 4.

 

 

Html.LabelFor Html. EditorForHtml.ValidationMessageFor

The Html.LabelFor helper displays the name of the field ("Title", "ReleaseDate", "Genre", or "Price").

 

"). The Html.EditorFor helper displays an HTML <input> element

 

The Html.ValidationMessageFor helper displays any validation messages associated with that property.

 

 

Html.DisplayFor

       显示表的字段名

 

 

 

 

 

 

Controller里面 [HttpPost]  ActionResult Edit。查看页面源码,form method=post. 编辑将触发

<![if !vml]><![endif]>

 

 

ModelState.IsValid (验证数据)

The ASP.NET MVC model binder takes the posted form values and creates a Movie object that's passed as the movie parameter. The ModelState.IsValid method verifies that the data submitted in the form can be used to modify (edit or update) a Movie object. If the data is valid, the movie data is saved to the Movies collection of the db (MovieDBContext instance). The  new movie data is saved to the database by calling the SaveChanges method of MovieDBContext. After saving the data, the code redirects the user to the Index action method of the MoviesController class, which  displays the of movie collection, including the changes just made..

 

禁用Get 方法修改数据

Modifying data in an HTTP GET method is a security risk, as described in the blog post entry ASP.NET MVC Tip #46 – Don’t use Delete Links because they create Security Holes

 

 

 

Linq简介

. LINQ的处理的核心对象就是IEnumerable可枚举对象也包括了泛型枚举,换句话说当你要处理的对象为IEnumerable类型对象时即可使用LINQ操作它

 

语法说明,每个LINQ语句都以from作为开头,以select作为结束,这点和T-SQL语法不通的切记先入为主的思考。其他关键字如where则类似T-SQL作为筛选判断条件。

 

样例:IEnumerable<T> nums = from n in nums where ....orderby... select....

 

  1. 关键字var : 

    指示编译器根据初始化语句右侧的表达式推断变量的类型。 推断类型可以是内置类型、匿名类型、用户定义类型或 .NET Framework 类库中定义的类型。这样我们就可以在上述的LINQ表达式中 例如可简写为:

 var nums = from in nums where .... orderby... select....

 

 

实例:

(1)

AList, B:List.  AB中共有的 添加到List C

IEnumerable<int> C = from a in A

                     from b in B

                     where a==b

                     select a;

 

 

 

 

(2)

普通查询

var query = from num in num

            select num.ProperyA

  筛选查询

var query = from obj in objs

            where obj.ProperyA > Condition

            select obj

  分组查询

var query = from obj in objs

            groupobj by obj.PropertyA into g

            orderby g.Key

            select g;

      注意,在此示例里,关键字 into 不是必须的,使用 into 时,必须继续编写该查询,并最终用一个 select 语句或另一个 group 子句结束该查询。

   内联查询

var query= from obj1 in objs1

           join obj2 in objs2 on obj1.ID equals obj2.ID

           selectnew { A= obj1.Property, B = obj2.Property };

  左外联查询

var query = from obj1 in objs1

            join obj2 in objs2 on obj1.ID equals obj2.Obj1ID into g

            from subpet in g.DefaultIfEmpty()

            selectnew { P1 = obj1.P1, P2 = (subpet == null ? null : subpet.P2 ) };

 

 

 

添加Search方法

1)在MovieController中添加 ActionResult

   public ActionResult SearchIndex(string key)

        {

            var movies = from model in db.MoviesModel

                         select model;

            if (!String.IsNullOrEmpty(key))

            {

                movies = movies.Where(s => s.Title.Contains(key));

            }

            return View(movies);

        }

 

2)为ActionResult添加VIew

<![if !vml]><![endif]>

这样,会生成

SearchIndex.cshtml视图。

 

3)检测关键字搜索功能:

       url中输入以下

http://localhost:1379/Movies/SearchIndex?key=

<![if !vml]><![endif]>

 

 

http://localhost:1379/Movies/SearchIndex?key=Harry

<![if !vml]><![endif]>

这就是搜索功能

 

现在改成按id搜索

 

添加输入框

 

Lambda表达式  =>

常用在Linq语句的条件中

http://msdn.microsoft.com/en-us/library/bb397687.aspx

相当于 匿名函数。  x=>x*x

=>左侧是函数参数

=>右侧是函数体

返回值就是 函数体的值。

 

 

 

 

Html.BeginForm

The Html.BeginForm helper creates an opening <form> tag. The Html.BeginForm helper causes the form to post to itself when the user submits the form by clicking the Filter button.

 

从前台控制调用 Get方法还是HttpPost方法

//调用Get方法

    @using (Html.BeginForm("SearchIndex", "Movies", FormMethod.Get))

    {   

         <p> Title: @Html.TextBox("SearchString") 

         <input type="submit" value="Filter" /></p>

}

 

//调用Post方法

    @using (Html.BeginForm("SearchIndex", "Movies", FormMethod.Post))

    {   

         <p> Title: @Html.TextBox("SearchString") 

         <input type="submit" value="Filter" /></p>

}

 

 

按名称搜索

       Controller中添加

        public ActionResult SearchIndex(string key) //输入Movies/SearchIndex时调用按名称搜索

        {

            var movies = from model in db.MoviesModel

                         select model;

            if (!String.IsNullOrEmpty(key))

            {

                movies = movies.Where(s =>s.Title.Contains(key));

            }

            return View(movies);

        }

 

右键点击SearchIndex内部,àAdd View

<![if !vml]><![endif]>

 

SearchIndex.cshtml中添加 被注释的部分

  @Html.ActionLink("Create New", "Create")

    <!--@using (Html.BeginForm("SearchIndex", "Movies", FormMethod.Get))

    {   

         <p> Title: @Html.TextBox("key")  <!--textBox的名称要和ActionResult的形参同名-->

         <input type="submit" value="Filter" /></p>

    } 按名称搜索-->

 

Search By Genre Genre和名称搜索

Controller中的SearchIndex Action替换成

public ActionResult SearchIndex(string movieGenre, string searchString) //输入Movies/SearchIndex时调用按名称搜索

        {

            var GenreLst = new List<string>();

 

            var GenreQry = from d in db.MoviesModel

                           orderby d.Genre

                           select d.Genre;

            GenreLst.AddRange(GenreQry.Distinct());

            ViewBag.movieGenre = new SelectList(GenreLst);

 

            var movies = from m in db.MoviesModel

                         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));

            }

        }

 

 

修改Model的字段,通过Initializer自动重建数据库

//备注:这样会删除已有的所有数据。

1)在Model中添加字段

2)在Model目录下添加MovieInitializer

3)在Globe.asax页的Application_Start的第一句添加上

         Database.SetInitializer<DbMovieContext>(new MoviesInitialter());

Validating Model (输入数值 validating)

       当用户add Edit时候,确保MovieModel输入有效

 

MVCEF “DRY” (dont repeat yourself) 理念

The validation support provided by ASP.NET MVC and Entity Framework Code First is a great example of the DRY principle in action. You can declaratively specify validation rules in one place (in the model class) and the rules are enforced everywhere in the application.

1)在MoviesModel中添加引用 System.ComponentModel.DataAnnotations

2)给MoviesModel的字段添加 约束条件(validation condition

Now update the Movie class to take advantage of the built-in Required, StringLength, and Range validation attributes. Use the following code as an example of where to apply the attributes.

常见约束条件(放在属性前面)

必填       [Required]

日期类型   [DataType(DataType.Date)]

数值范围   [Range(1,100)]

字符串最大长度  [StriingLength(5)]

 

如下代码会报错:

MovieDBContext db =newMovieDBContext(); 
Movie movie =newMovie(); 
movie.Title="Gone with the Wind"; 
movie.Price=0.0M; 
db.Movies.Add(movie);   

db.SaveChanges();        // <= Will throw validation exception

 

总结:

       不需要改变ControllerView只要在Model字段的属性上添加即可

 

 

Validate方法在哪被执行

MovieController.cs   (ModelState.IsValid) 会检查Model中的所有Validation

        //

        // GET: /Movies/Create

        public ActionResult Create()

        {

            return View();

        }

 

        [HttpPost]

        public ActionResult Create(MoviesModel moviesmodel)

        {

            if (ModelState.IsValid)

            {

                db.MoviesModel.Add(moviesmodel); //moviesmodel 是一条记录

                db.SaveChanges();

                return RedirectToAction("Index");

            }

 

            return View(moviesmodel);

        }

 

 

The first (HTTP GET) Create action method displays the initial Create form. The second handles the form post. The second Create method (The HttpPost version) 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. In our movie example we are using, the form is not posted to the server when their are validation errors detetected on the client side; the second Create method is never called. If you disable JavaScript in your browser, client validation is disabled and the second Create method calls ModelState.IsValid to check whether the movie has any validation errors.

 

Format Setting(控制显示格式)

Open the Movie.cs file and examine the Movie class. The System.ComponentModel.DataAnnotations namespace provides formatting attributes in addition to the built-in set of validation attributes. We've allready applied the DisplayFormat attribute and a DataType enumeration value to the release date and to the price fields. The following code shows the ReleaseDate and Price properties with the appropriate DisplayFormat attribute.

同时添加约束和格式限制

    [Range(0,100)][DataType(DataType.Currency)]

        public decimal Price { get; set; }

 

 

DetailsExamine

//hacker通过输入错误url看数据库错误,获取漏洞

Code First makes it easy to search for data using the Find method. An important security feature built into the method is that the code verifies that the Find method has found a movie before the code tries to do anything with it. For example, a hacker could introduce errors into the site by changing the URL created by the links from http://localhost:xxxx/Movies/Details/1 to something like http://localhost:xxxx/Movies/Details/12345 (or some other value that doesn't represent an actual movie). If you did not check for a null movie, a null movie would result in a database error.

 

 

Note that the HTTP Get Delete method doesn't delete the specified movie, it returns a view of the movie where you can submit (HttpPost) the deletion.. Performing a delete operation in response to a GET request (or for that matter, performing an edit operation, create operation, or any other operation that changes data) opens up a security hole. For more information about this, see Stephen Walther's blog entry ASP.NET MVC Tip #46 — Don't use Delete Links because they create Security Holes.

 

如何寻址两个Delete方法?

The HttpPost method that deletes the data is named DeleteConfirmed to give the HTTP POST method a unique signature or name. The two method signatures are shown below:

<![if !vml]><![endif]>

The common language runtime (CLR) requires overloaded methods to have a unique signature (same method name but different list of parameters). However, here you need two Delete methods -- one for GET and one for POST -- that both have the same signature. (They both need to accept a single integer as a parameter.)

To sort this out, you can do a couple of things. One is to give the methods different names. That's what the scaffolding mechanism did in he preceding example. However, this introduces a small problem: ASP.NET maps segments of a URL to action methods by name, and if you rename a method, routing normally wouldn't be able to find that method. The solution is what you see in the example, which is to add the ActionName("Delete") attribute to the DeleteConfirmed method. This effectively performs mapping for the routing system so that a URL that includes /Delete/ for a POST request will find the DeleteConfirmed method.

 

 

 

 

DIY Movie

1)增删改

2)查  Controller中添加方法。

public ActionResult SearchIndex(string movieGenre, string searchString) 

    var GenreLst = new List<string>(); 

 

    var GenreQry = from d in db.Movies 

                   orderby 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)); 

    } 

}

 

添加SearchIndex(view),并在上面添加UI

                  @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>

        }

 

(3)添加字段

>Model中添加字段

>Model目录下添加MovieInitializer

public class MoviesInitializor : DropCreateDatabaseIfModelChanges<MovieDbContext>

    {

        protected override void Seed(MovieDbContext context)

        {

            var movies = new List<Movie> {  

                 new Movie { Title = "When Harry Met Sally",   

                             ReleasedDate=DateTime.Parse("1989-1-11"),   

                             Genre="Romantic Comedy",  

                             Rating ="R",

                             Price=7.99M},  

 

                     new Movie { Title = "Ghostbusters ",   

                             ReleasedDate=DateTime.Parse("1984-3-13"),   

                             Genre="Comedy",

                             Rating ="R",

                             Price=8.99M},   

  

                 new Movie { Title = "Ghostbusters 2",   

                             ReleasedDate=DateTime.Parse("1986-2-23"),   

                             Genre="Comedy",    

                             Rating ="R",

                             Price=9.99M},   

 

               new Movie { Title = "Rio Bravo",   

                             ReleasedDate=DateTime.Parse("1959-4-15"),   

                             Genre="Western", 

                             Rating ="R",

                             Price=3.99M},   

             };

 

            movies.ForEach(d => context.Movies.Add(d));

        }

    }

 

>Globe.asax页的Application_Start的第一句添加上

         Database.SetInitializer<DbMovieContext>(new MoviesInitialter());

>View(Index,Edit,Delete,Details)添加显示

      

 

posted on 2012-07-08 10:49  imihiro  阅读(958)  评论(0编辑  收藏  举报