凯发k8天生赢家一触即发

【第一篇】asp.net mvc快速入门之数据库操作(mvc5 ef6) -凯发k8天生赢家一触即发

2023-08-17,,

【】asp.net mvc快速入门之数据库操作(mvc5 ef6)

【第二篇】asp.net mvc快速入门之数据注解(mvc5 ef6)

【第三篇】asp.net mvc快速入门之安全策略(mvc5 ef6)

【第四篇】asp.net mvc快速入门之完整示例(mvc5 ef6)

【番外篇】asp.net mvc快速入门之免费jquery控件库(mvc5 ef6)

请关注三石的博客:http://cnblogs.com/sanshi

新建项目

打开vs2015,找到菜单项[文件->新建->项目],打开向导对话框:

注意我们的选择项:

1.     运行平台:.net framework 4.5

2.     项目模板:asp.net web application (.net framework)

3.     项目名称:aspnetmvc.quickstart,如果你在跟着本教程练习,建议起相同的项目名称,方便直接拷贝代码到你的项目中。

点击[确定]按钮,向导会带我们到另一个选择对话框:

由于本教程是快速入门,所以我们从最简单的入手,只勾选必需的选项:

1.     不进行身份验证。asp.net mvc提供了完善的身份验证方案,我们会有单独的文章讲解。

2.     仅勾选 mvc 引用。

点击[确定],vs2015会创建一个可直接运行的项目,按下快捷键[ctrl f5],不调试直接运行:

默认的目录结构如下:

如果你之前在webforms下进行开发,对其中的一些文件夹和文件应该很熟悉了:

1.     web.config:项目配置文件,里面保存项目配置参数以及数据库连接字符串。

2.     packages.config:nuget配置文件

3.     global.asax:全局代码文件,提供应用程序级别以及会话级别的事件处理函数,可以在application_start中注册全局变量。

4.     favicon.ico:浏览器地址栏图标,在html的head标签中引用。

5.     app_data:放置本地数据库文件,比如localdb生成的数据库文件。

下面几个文件夹,用来放置静态文件,从名称就可以方便的猜出其用途:

1.     scripts:放置静态脚本文件,比如jquery等。

2.     fonts:放置图标字体文件,比如流行的fontawesome字体等。

3.     content:放置静态文件,比如xml文件、bootstrap的css库。

下面几个文件是asp.net mvc新引入的:

1.     app_start:用来放置应用初始化类,这个是mvc4引入的一个命名约定,其实这就是一个普通的文件夹,没有特殊的含义。

2.     controllers:控制器类。

3.     models:模型类,比如ef codefirst的模型定义。

4.     views:视图文件,最初的视图引擎是webforms view engine,使用和aspx文件相同的语法,而现在用的razor视图引擎是mvc3引入的,以cshtml为后缀。

页面流程

首先看下 [about]页面:

这个页面之所以能够呈现在我们眼前,经历了三个主要流程:

1.     mvc的路由引擎根据url查找相应的控制器(homecontroller.cs)。

2.     控制器的操作方法about准备数据,然后传入视图home/about.cshtml。

3.     视图准备html片段,放入布局页面并返回浏览器。

路由引擎->控制器

一切还得从global.asax中说起,在其中的应用程序启用事件中,我们需要注册路由处理器:

protected void application_start()
{
arearegistration.registerallareas();
filterconfig.registerglobalfilters(globalfilters.filters);
routeconfig.registerroutes(routetable.routes);
bundleconfig.registerbundles(bundletable.bundles);
}

routeconfig.cs类位于app_start文件夹中,我们来看下内容:

public class routeconfig
{
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 }
);
}
}

这里注册一个名为default的路由规则,对应的url是{controller}/{action}/{id},这里三个占位符分别表示:

1.     {controller}:控制器,默认是home,对应的控制器类是homecontroller.cs。

2.     {action}:控制器里面的方法,默认是index。所以如果用户直接通过http://localhost/访问系统时,默认调用home控制器中的index方法处理。

3.     {id}:参数id,可选项,这个参数对应于操作方法中的id参数。

控制器方法->视图

通过上面的介绍,我们就知道了http://localhost:55654/home/about网址对应于home控制器的about方法。

我们在controllers/homecontroller.cs中找到相应的方法:

public actionresult about()
{
viewbag.message = "your application description page."; return view();
}

viewbag是一个动态对象(dynamic),可以用来存储任意参数,用来从控制器向视图传递数据。

从控制器向视图传递数据一般有两种方法:

1.     传入模型,然后在视图中通过model对象访问,这是一种强类型的方式,也是推荐的做法。其局限性就是只能传入一个模型,如果需要传入多个模型对象,就需要自定义类来包含多个模型,另一种方法就是viewbag。

2.     viewbag,视图包传递数据非常方便,但是在视图中可能需要进行强制类型转换。在常见的传入一个主模型和多个次模型时,可以把多次模型放到viewbag中,从而避免自定义类的麻烦。

作为命名约定,这个操作方法会自动调用相应名称的视图文件about.cshtml。

视图->浏览器

下面来看about.cshtml视图文件:

@{
viewbag.title = "about";
}

@viewbag.title.


@viewbag.message

use this area to provide additional information.

以@开头用来输出c#代码的运行结果,mvc会自动判断于何处结束c#代码,并转入html代码。

需要注意,页面第一行的@{ }用来执行一段c#代码,不会输出内容,这里定义了一个viewbag.title的变量,并在下面的代码中使用@viewbag.title输出到页面中。

很多初学者可能有些疑惑,为啥控制器中定义了viewbag.message,而在视图中定义了viewbag.title,这两者有啥区别?

一般来说是没有功能的区别,仅仅是语义的区别。在视图中定义的变量仅在视图中使用,比如这里定义的viewbag.title不仅在about.cshtml中使用,而且在布局视图shared/­_layout.cshtml中也用到了。

布局视图

布局视图类似于webforms中的母版页,具体的视图页面会作为一部分嵌入到布局视图中,然后返回到浏览器形成一个完整的页面。

每一个视图页面默认会使用views/_viewstart.cshtml中的定义的内容:

@{
layout = "~/views/shared/_layout.cshtml";
}

这里面指定了布局视图的位置,我们来简单看下布局视图的内容:






<strong>@viewbag.title</strong> - my asp.net application
@styles.render("~/content/css")
@scripts.render("~/bundles/modernizr")




@renderbody()



© @datetime.now.year - my asp.net application



@scripts.render("~/bundles/jquery")
@scripts.render("~/bundles/bootstrap")
@rendersection("scripts", required: false)

其中head标签下面的title中使用了在about视图中定义的viewbag.title属性。

这个布局视图使用bootstrap库定义的css样式来完成,包含标题栏,导航菜单,以及页脚的定义,具体的内容会嵌入@renderbody()的地方,最终形成完整的html页面返回。

数据库操作

上面从控制器传入视图的数据是硬编码的一个字符串,实际项目中则经常需要从数据库中读取数据,我们使用微软推荐的entity framework codefirst开发模式来创建和使用数据库。

安装entity framework

首先需要安装ef,在vs2015中找到[工具]菜单,然后找到nuget包管理器:

转到[浏览]选项卡,可以搜索entity framework,安装其最新稳定版到项目中:

安装后,会自动更改web.config添加相应的配置信息。

创建模型

我们计划完成一个简单的学生管理系统,包含基本的增删改查(crud)。

首先在models文件,创建学生(student)的模型类:

public class student
{
public int id { get; set; }
public string name { get; set; }
public int gender { get; set; }
public string major { get; set; }
public datetime entrancedate { get; set; }
}

然后创建数据库操作上下文,ef需要这个文件来创建和访问数据库:

public class studentdbcontext : dbcontext
{
public dbset students { get; set; }
}

由于这个类继承自ef的dbcontext基类,因此需要在文件头部添加如下引用:

using system.data.entity;

创建完这两个文件,需要重新编译项目(快捷键ctrl shift b),否则下面添加控制器时会出错。

添加控制器

在controllers目录上点击右键,添加控制器,弹出向导对话框:

这里选择 mvc 5 controller with views, using entity framework,然后进入设置对话框:

在这个对话框中,我们需要指定刚才创建的模型类(student)和数据访问上下文类(studentdbcontext),然后vs不仅可以自动创建视图,而且使用ef自动创建crud的全部代码,是不是很酷!

全部功能完成了!

是不是很惊奇,我们甚至没来得及写视图代码,没有配置数据库,没有写crud的逻辑代码,vs模板帮我们生成了一切,现在运行一下(ctrl f5),并在浏览器中输入/students:

表格页面

表格页面对应于students控制器下的index操作方法:

public class studentscontroller : controller
{
private studentdbcontext db = new studentdbcontext(); // get: students
public actionresult index()
{
return view(db.students.tolist());
} }

首先,我们看到控制器内部定义了一个私有变量db,并进行初始化。这是数据库操作上下文实例,所有的crud操作都讲依赖于这个实例。

在index方法中,通过向view方法传递学生列表的方式,把模型数据传递到了视图,在views/students/index.cshtml视图文件中,我们声明了传入模型的类型:

@model ienumerable

在视图中,model属性的类型就确定为强类型ienumrable,配合vs提供的智能感知,不仅可以快速编写代码,并且在编译时还检查代码的有效性。

完整的index.cshtml代码:

@model ienumerable
@{
viewbag.title = "index";
}

index


@html.actionlink("create new", "create")









@foreach (var item in model) {







}

@html.displaynamefor(model => model.name)

@html.displaynamefor(model => model.gender)

@html.displaynamefor(model => model.major)

@html.displaynamefor(model => model.entrancedate)

@html.displayfor(modelitem => item.name)

@html.displayfor(modelitem => item.gender)

@html.displayfor(modelitem => item.major)

@html.displayfor(modelitem => item.entrancedate)

@html.actionlink("edit", "edit", new { id=item.id }) |
@html.actionlink("details", "details", new { id=item.id }) |
@html.actionlink("delete", "delete", new { id=item.id })

看着很有古老的asp的感觉吧,不过这里的model属性是强类型的,因此在foreach循环中,vs明确知道item类型是student,从而方便代码编写:

@html里面都是mvc提供的辅助方法,用来辅助生成html代码:

1.     actionlink:用来生成超链接,链接到本控制器内的某个操作方法(也可以是其他控制器的方法,有重载函数),可以指定路由参数,通过对象初始化语法来创建,比如new {id=item.id}。

2.     displaynamefor:显示模型属性的名称。强类型辅助方法,允许我们使用一个lambda表达式来指定某个模型属性,而不用写字符串。好处不仅有智能感知,编译时检查,而且也方便代码重构,比如我们在更改模型的属性名称时,视图中的相应代码也会改变。

3.     displayfor:显示模型属性的值。

新增页面

新增页面对应于students控制器下的create操作方法:

// get: students/create
public actionresult create()
{
return view();
}

对应的视图文件:

@model aspnetmvc.quickstart.models.student
@{
viewbag.title = "create";
}

create

@using (html.beginform())
{
@html.antiforgerytoken()

student




@html.validationsummary(true, "", new { @class = "text-danger" })

@html.labelfor(model => model.name, htmlattributes: new { @class = "control-label col-md-2" })

@html.editorfor(model => model.name, new { htmlattributes = new { @class = "form-control" } })
@html.validationmessagefor(model => model.name, "", new { @class = "text-danger" })

@* 省略 gender major entrancedate *@






}

@html.actionlink("back to list", "index")
@section scripts {
@scripts.render("~/bundles/jqueryval")
}

首先定义了视图中使用的模型类型是student,这样labelfor强类型辅助方法就可以从模型元数据中获取需要显示的文本。

页面打开时,由于并未传入任何模型对象,所以model为空对象,如下所示:

所以页面上默认的输入框都是空的,截图中是作者输入值后的效果。

html.beginform()会在页面上生成一个form标签,默认的提交地址还是当前页面(action=/students/create),默认的请求方法是post,如下所示:

因此,点击[create]按钮时,会发出一个post请求到后台,对应于students控制器的create方法。

保存数据与模型绑定

下面我们来看下拥有[httppost]元数据的create方法:

[httppost]
[validateantiforgerytoken]
public actionresult create([bind(include = "id,name,gender,major,entrancedate")] student student)
{
if (modelstate.isvalid)
{
db.students.add(student);
db.savechanges();
return redirecttoaction("index");
} return view(student);
}

这里面有两个安全措施:

1.     validateantiforgerytoken:用来阻止csrf(跨站请求伪造)。

2.     bind:用来阻止over-posting(过多提交攻击)。

这两个安全手段我们会在以后的文章中详细介绍,这里就先略过。

我们先看下本次请求的post参数:

但是create方法中只有一个student对象参数,是不是很神奇,其实这是一个重要的概念模型绑定

如果在webforms中,我们可以会写一堆代码来从request.form中获取参数,并重建student对象,类似如下代码:

student student = new student();
student.name = request.form["name"];
student.gender = convert.toint32(request.form["gender"]);
....

在mvc中,这一过程是自动完成,简单来说这就是模型绑定。

但是实际的模型绑定过程,不仅在请求的表单数据中查找,还会在路由参数,url查询字符串,以及cookie中查找。

如果模型绑定失败(比如模型参数不符合验证规则),则modelstate.isvalid就为false,这时会直接返回页面内容,此时模型对象student中保存的是用户输入的值,前端也会有错误提示,这个过程我们会在下一篇文章中讲解。

如果模型绑定成功,则保存新增数据,然后通过redirecttoaction来重定向到表格页面:

小结

这篇文章首先介绍了vs2015下mvc项目的创建过程;然后简要概述页面执行的流程,从路由引擎到控制器,再由控制器到视图,最后由视图返回到浏览器,而模型是作为控制器传入视图的参数,这样清晰明了;最后使用vs提供的模板,创建了一个带crud操作的数据访问实例。

ef codefirst让我们的关注点从数据库转移到了模型,而模型又是mvc的核心所在,对模型进行恰当的数据注解,不仅会影响数据库的表结构,而且会影响浏览器端的数据验证和服务端的数据验证,因此下一篇文章我们会详细介绍一下数据注解。

下载示例源代码

【第一篇】asp.net mvc快速入门之数据库操作(mvc5 ef6)的相关教程结束。

网站地图