• ASP.NET MVC3+EF4+Oracle入门实例(七)


    7.9 从控制器访问模型数据

    本节,您将创建一个新的MoviesController类并编写代码读取电影数据并用视图模板在浏览器中显示他们。在继续前,请先编译你的应用程序,不然下面找不到模型类。

    右键Controllers文件夹新建一个MoviesController控制器。选择下面的选项:

    · Controller name: MoviesController. (默认. )

    · Template: Controller with read/write actions and views, using Entity Framework.

    · Model class: MOVIE (MvcMovie.DAL)

    · Data context class: MovieEntities (MvcMovie.DAL)

    · Views: Razor (CSHTML). (默认.)

    clip_image002

    单击“Add”。Visual Studio创建了下面的文件夹和文件:

    1. 在项目的Controller文件夹下MoviesController.cs文件

    2. 在项目的View文件夹下Movies文件夹

    3. 在新创建的文件夹Views\Movies下Create.cshtml, Delete.cshtml,
    Details.cshtml, Edit.cshtml, and Index.cshtml。

    clip_image004

    ASP.NET MVC 3架构机制自动创建CRUD(create, read, update, and delete)响应方法和视图。您现在拥有了全部的web应用程序的功能,支持增加、显示、编辑、删除电影作品。

    运行应用程序并通过在浏览器地址栏中URL后追加/Movies来浏览Movies控制器。因为应用程序依托默认的路由(在Global.asax文件中定义),浏览请求http://localhost:xxxxx/Movies被路由到Movies控制器的默认方法Index。换句话说,http://localhost:xxxxx/Movies实际上和http://localhost:xxxxx/Movies/Index是一样的。因为您还没有添加任何东西,所以电影列表是空的。

    clip_image006

    7.10 创建电影

    选择“Create New”链接。输入一个电影的详细信息然后单击“Create”按钮。

    clip_image008

    单击“Create”按钮使页面回发到服务器端(那里的电影信息将会保存在数据库中)。您将重定向到/Movies URL,在列表里您能看到刚被添加的电影信息。

    此时,Visual Studio还自动实现了数据验证,在上图的创建页面,不输入信息,然后点击“Create”会出现如下结果(后面我们会介绍自定义模型验证):

    clip_image010

    运行结果:

    clip_image012

    查看数据库:

    clip_image014

    您可以创建一些电影作品,测试全部的功能,编辑、明细、删除。

    7.11 审视代码

    打开Controllers\MoviesController.cs文件并审视生成的Index方法代码。部分控制器Index方法的代码如下所示:

    public class MoviesController : Controller
        {
            private MovieEntities db = new MovieEntities();
    
            //
            // GET: /Movies/
    
            public ViewResult Index()
            {
                return View(db.MOVIEs.ToList());
            }
    }
    

    如前面所述,下面的行在MoviesController类中实例化了一个电影数据库的内容。

    private MovieEntities db = new MovieEntities();

    Movies控制器返回数据库中的所有电影资料实体并把结果传递给Index视图。

    强类型模型和@model关键字

    在教程的前面部分,您了解了如何使用ViewBag对象把数据通过控制器传递给视图。ViewBag是一个动态对象,提供了方便的迟绑定方式将信息传递给视图。

    ASP.NET MVC也支持传递强类型数据给视图模板。这种强类型的方式支持编译时检查代码和丰富的智能感知。我们将在MoviesController类和Index.cshtml视图模板中采用这种方式。请注意该代码创建一个List对象时调用Index方法中View Helper方法。代码通过控制器传递电影列表给视图:

    public ViewResult Index()
            {
                return View(db.MOVIEs.ToList());
            }
    

    通过在视图模板文件的顶部包含@model表达式,您可以指定在视图中您期望使用的对象类型。当您创建电影控制器的时候,Visual Studio自动在视图模板文件Index.cshtml的顶部包含@model表达式:@model IEnumerable<MvcMovie.DAL.MOVIE>

    @model指令允许您访问由控制器使用强类型Model对象传递给视图的电影列表。比如,Index.cshtml模板,代码通过foreach表达式遍历了基于强类型的电影资料。

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.TITLE)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.RELEASEDATE)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.GENRE)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PRICE)
            </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>
    }
    

    由于实体对象是强类型(被用作可枚举对象),循环中的每个item对象都是强类型的Movie。其他好处指的是编译时检查代码和全部的智能感知支持。

    clip_image002

    您现在拥有了数据库并通过简单的列表展现了他们。

    审视编辑方法和视图

    在这一节中,您将审视Movies控制器生成的响应方法和视图。然后您将添加

    一个自定义搜索页面。运行程序并通过在URL追加/Moives浏览movie控制器。把鼠标悬停在Edit链接上,看看它执行的URL.

    clip_image004

    Edit的链接由视图Views\Movies\Index.cshtml 的Html.ActionLink方法生成。

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

    clip_image006[5]

    Html对象是一个助手,它是WebViewPage基类暴露的属性。助手的ActionLink方法可以很容易的生成HTML超链接,它指向控制器的响应方法。ActionLink的第一个参数表示超链接的文本呈现(比如:<a>Edit Me</a>),第二个参数是要调用的响应方法的名称,最后一个参数生成路由数据的匿名对象(anonymous object,这里指ID=4)。

    您可以使用查询字符串(query string)传递参数给响应方法。比如URLhttp://localhost:xxxxx/Movies/Edit?ID=4传递ID=4给Movies控制器的Edit方法。

    clip_image008[5]

    打开Movies控制器。有两个Edit方法,如下所示:

    // GET: /Movies/Edit/5
    
           public ActionResult Edit(decimal id)
           {
               MOVIE movie = db.MOVIEs.Single(m => m.ID == id);
               return View(movie);
           }
    
           //
           // POST: /Movies/Edit/5
    
           [HttpPost]
           public ActionResult Edit(MOVIE movie)
           {
               if (ModelState.IsValid)
               {
                   db.MOVIEs.Attach(movie);
                   db.ObjectStateManager.ChangeObjectState(movie, EntityState.Modified);
                   db.SaveChanges();
                   return RedirectToAction("Index");
               }
               return View(movie);
           }
    

    注意第二个Edit方法前面是HttpPost属性。它表明这个重载的Edit方法只能被

    POST请求调用。您也可以给第一个Edit方法采用HttpGet属性,但是这不是必须的,应为方法默认为HttpGet(响应方法隐含的了HttpGet属性将被认为是HttpGet方法)。

    HttpGet方法将电影的ID作为参数,并使用实体框架的Find方法查找电影,然后返回被找到的电影给视图模板。当架构体系创建编辑模板时,它检查Movie类并为每个属性生成<label><input>代码去呈现元素。下面的代码展示了自动生成的Edit视图模板:

    @model MvcMovie.DAL.MOVIE
    
    @{
        ViewBag.Title = "Edit";
    }
    
    <h2>Edit</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>
    
            @Html.HiddenFor(model => model.ID)
    
            <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>
    
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    

    <form>中的<input>元素表示一个提交按钮,点击时将提交页面数据到Controller中的Edit方法。

    处理POST请求

    由架构体系生成的属性为HttpGet的Edit方法没有检查传给它的ID的有效性。如果用户删除URL的ID字段,错误信息如下所示:

    clip_image002[5]

    用户还可以传递一个不存在的ID,比如:

    http://localhost:xxxxx/Movies/Edit/1234.您可以给HttpGet Edit方法做两点修改来限制URL。首先,把ID参数改为默认值为0 (id不是必须传递)。

    您也可以在回传电影对象给视图模板之前,检查Find方法是否真正的找到了电影信息。

    public ActionResult Edit(decimal id=0)
            {
                MOVIE movie = db.MOVIEs.FirstOrDefault(m => m.ID == id);
                if(movie==null)
                {
                    return HttpNotFound();
                }
                return View(movie);
            }
    

    如果没有找到,HttpNotFound方法被调用。

    所有的HttpGet方法都遵循类似的模式。它们获取一个电影对象(在Index中返回对象列表),然后传递模型给视图。Create方法传递一个空电影对象给Create视图。所有的方法(创建、编辑、删除)都有一个HttpPost的重载方法。

    在HTTP GET方法中修改数据存在安全风险,在博客ASP.NET MVC Tip #46 – Don’t use Delete Links because they create Security Holes中有描述。在HTTP GET方法中修改数据违反了HTTP的最佳实践和REST架构模式(其中规定GET请求不应改变应用程序状态)。换句话,执行GET操作应该是一个无副作用的安全操作。

  • 相关阅读:
    第06组 Beta冲刺(4/5)
    第06组 Beta冲刺 (3/5)
    第06组 Beta冲刺 (2/5)
    第06组 Beta冲刺 (1/5)
    Attention与Transformer学习【更新中】
    【李沐】动手学深度学习-pytorch 2021版 softmax回归的简洁实现
    【李沐】动手学深度学习-pytorch 2021版 从零开始实现softmax回归
    [Java]剑指offer:矩阵中的路径
    [Java]剑指offer:平衡二叉树
    [Java]剑指offer:链表中倒数第k个结点
  • 原文地址:https://www.cnblogs.com/yuananyun/p/2137397.html
Copyright © 2020-2023  润新知