在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本系类教程将要构建ASP.NET MVC 5 Web 应用程序,使用的工具是VS2013 。现在有预览版可以下载了, 点击下载VS2013 FOR WEB ISO文件 。VS2012 还没用几天呢,2013就要出来,据说数据库有SQL2014的版本了。不带这么玩的!!! Go 安装完VS2013 for Web 后,打开在起始页(start page)选择新建项目。 可以发现和VS2012最大的不同,WEB里面只有一个选择,确定后接下来才开始选择其他的: VS2012 还有MVC3 MVC4选择,在VS2013没得选。好了,创建项目后,我们直接按下F5运行。 好了,一个网站OK了。拥有 首页、关于、联系方式等页面。更NB的是注册登录也有了。 查看了下网页源代码,前端用的是大名鼎鼎的 bootstrap。有时间会专门写这个系类的文章。 ASP.NET MVC 5 入门二 添加控制器发表于 2013 年 8 月 13 日 由 颜晋南 什么是MVC?MVC就是 Models 模型,Views 视图,Controllers 控制器。MVC虽然分为3个部分,但是和三层没有关系,是一种用来开发应用程序的模式具有良好的架构,易于维护和测试。
下面让我们添加一个控制器类,在资源管理器 项目里面的Controllers 右击。 接下来去个名字吧,第一个实例一般都喜欢用 helloworld 。 我们把代码改成如下,直接返回string字符串在浏览器窗口。
按下F5,在默认的网页地址后面加上Helloworld,如下图: 一回车,就会看到我们刚才写的字符串显示在页面上。 ASP.NET MVC 会根据传入的URL调用不同的控制器类(上面例子的HelloWorld)以及里面不同的方法(上面例子的Index、Welcome)。具体依据什么来判断调用的是哪个控制器,哪个方法在App_Start/RouteConfig.cs 文件里面设定。 如果直接访问域名,会默认调用 defaults里面的 Home控制器下面的Index方法,后面的ID是传入的参数等数据后面会介绍。 所以刚才我们浏览的地址:MVC默认的映射来解析的话控制器是 HelloWorld ,调用的方法是:Welcome 没有ID这个参数。接下来我们修改为以下代码:
给Welcome 方法传入2个参数,年龄默认是18 。接下来我们看看运行结果。 以前要获得GET方法传入的参数,需要写一句代码(request),现在MVC自动的帮我们绑定了,多方便!接下来我们把上面的那个代码中的age改成ID,浏览器地址后面添加 /3?name=yan 这次的Welcome后面加上了/3 刚好匹配到了ID,剩下的就匹配到了name这个参数。按照这个思路,是不是有办法让地址栏直接匹配到name,这样url里面就没有 ? 这个符号。 我们在App_start\RouteConfig.cs里面添加一个试试: 当然,默认的路由规则大多数情况下是很合适的,不需要去修改。接下来会介绍模型绑定,这样就不需要修改路由规则了。 下一步学习: 添加视图(View) ASP.NET MVC5 入门三——添加视图发表于 2013 年 8 月 16 日 由 颜晋南 在上一篇《 ASP.NET MVC5 添加控制器 》里面我们都是直接返回string 字符串或者html 。这样的话控制器不仅仅做了控制器的工作还做了VIEW(视图)的工作。通常我们不希望控制器直接返回HTML,因为那样子复杂的页面就会非常繁琐,所以我们通常会用一个单独的视图模板文件来辅助生产对应的html响应报文返回客户端。 接下来我们就来看看如何添加视图,先修改上篇博客的那个例子,我们来修改HelloWorldController类,这样才能让view的模板文件来封装要返回的html响应报文。 首先,创建一个视图文件夹 HelloWorld 。右键单击(view)——》添加——》新建文件夹。 注意名字一定要是 HelloWorld 因为控制器名字是 HelloWorldController 控制器必须是Controller结尾,视图文件夹的名字必须和控制器除了结尾的部分一样。也就是“约定优于配置”的理念。 接下来添加一个支架,选择 MVC5 视图—空 不带模型 点击添加,弹出的对话框把视图名字(View name)改为 Index 。其他保持默认然后确定。 可以看到多了一个 Index.cshtml的文件。在上面的</h2>后面添加如下的html代码: <p>这是一个View模板,来自于:HelloWorld下面的Index视图!</p> 然后在index.cshtml文件上面右键,选择在页面检查器中查看。当然也可以按下F5进行运行,在浏览器地址栏输入地址进行查看。 但浏览器的地址发到服务器的时候,服务器解析给控制器,然后控制器里面只有一句 return View()语句,指定返回一个视图模板文件给浏览器,我们没有写指定什么名字的视图,默认就是Index。 更改视图和布局页面首先,上一个页面我们需要修改标题,显示我们自己的信息。页面顶部在一个网站之中的每一页一般都是一样的所以我们来修改布局的页面也叫母版页。在解决方案资源管理器里面,打开/views/shared 里面的_Layout.cshtml文件。 可以看到,有很多@开头的内容,比如你能在body里面找到 @RenderBody() 这一行。这个什么意思呢?其实说白了就是一个占位符,到时候可以用具体的视图来填补这个信息。好比刚才那个Index.cshtml就是用来填补这里的。下面我们来修改标题,通过这个了解占位符,以及母版页(布局页)的作用。 在_Layout.cshtml 的头部,有个 <title>@ViewBag.Title – My ASP.NET Application</title> 我们修改为<title>@ViewBag.Title – 我的ASP.NET MVC5示例网站</title> 。body 里面的@Html.ActionLink(“Application name”, “Index”, “Home”, null, new { @class = “brand” }) 修改为 @Html.ActionLink(“MVC5示例网站”, “Index”, “Home”, null, new { @class = “brand” }) 回到刚才的Index.cshtml ,修改成如下: 然后按下F5运行看看。可以看到在浏览器顶端的标题是 首页1-我的ASP.NET。。。。 说明<title>@ViewBag.Title – 我的ASP.NET MVC5示例网站</title> 这句代码里面的 @ViewBag.Title 被Index.cshtml 里面对应的ViewBag.Title替换了。同时body里面被index.cshtml的内容填充了。 我们去About页面也能看到标题都变化了。这就是母版页的作用,我们能够在布局页面中修改一次,网站上的所有页面都显示新的标题。如果看不到效果的话可以CTRL+F5强制刷新看看。 上一篇的博文直接从M(模型)传HTML回去,这次貌似直接用V(视图),模型倒是没怎么用。接下来我们就创建一个数据库,通过M 模型 传递给 V 视图 来显示相应信息。 将数据从控制器传递到视图在我们建立数据库和模型之前,简单说下数据从控制器传递到视图。当服务器接收到浏览器一个url的请求,某个控制器的某个方法会来响应这次请求。控制器类就是那个我们写代码来解析浏览器传入的请求、分析业务、从数据检索出数据经过处理后最终决定返回什么样的数据给浏览器。然后视图VIEW就可以获得控制器传入的数据,进行整理封装成HTML返回给浏览器。控制器提供视图返回给浏览器需要的数据或者对象。所以,最好让视图不执行业务逻辑不与数据打交道,需要的数据就从控制器拿。这样才能保证“关注点分离”(SOC)。 回到我们昨天写的另外一个方法 Welcome 它需要2个参数,一个是name一个是ID。代码如下: ViewBage 是个动态的对象,意味着我们可以随时添加需要的属性。再添加之前ViewBag 并没有那个属性。借助于上个博客说的ASP.NET MVC的自动绑定模型,可以直接赋值给刚才动态创建的属性 Message 和 tiems。接下来我们按照之前的步骤在添加一个视图:Welcome 。 代码如下: 非常的简单,循环输出消息。F5运行在地址栏输入 当我们输入上面地址栏的那个地址时候,服务器传递给相应的控制器处理,控制器获得参数,把数据打包成一个ViewBag对象,并将该对象传递给视图,视图获得对象后取到需要的数据,组织好HTML语句然后返回给客户的浏览器。 接下来的教程,将会介绍使用视图模型来将数据从控制器传递到视图。利用视图模型的方法会比一般的方法好(强类型)。 下一步: 添加模型 额,M(model)的一种模型,不是数据库的那种 。 ASP.NET MVC5 入门四——添加模型发表于 2013 年 8 月 19 日 由 颜晋南 在本节中,我们将要添加一些类来管理数据库中的信息。MVC入门系类的文章打算建立一个电影网站的示例。在前几篇的博客《 Entity Framework学习——了解 》,我介绍了新的编程方式 Code First 。所以我们应该添加一些类来作为MVC中的“模型”部分。 添加模型类在解决方案资源管理器中,右键单击 Models 文件夹,选择添加,然后选择类: 输入类名“Movie”。 向类“Movie”添加以下5个属性:
从上面的代码可以看出,这个就是用类(class)来表示数据库中的电影(电影数据信息)。类的每个实例对应着数据库中的每行,类的属性对应着数据库中的每列。 在Movie中继续添加代码,我们添加一个 MovieDBContext 类: 可以看出,MovieDBContext 继承至 DbContext 。我们需要应用Entity,可以手动加入以下的using System.Data.Entity;语句或者像上图那样,在红色错误处右键选择解析,然后自动添加引用。我们也会发现,有些应用我们不需要,按照下图方式清除未使用的using语句:
上面就是最终的代码,清爽许多。这也是我喜欢.NET 胜过JAVA的原因,有个强大的IDE。非常方便,使用起来容易上手。对于中小企业,快速的开发出合格产品才是王道! 下一节: 添加数据库连接字符串和LocalDB 。 ASP.NET MVC5 入门五——使用LocalDB发表于 2013 年 8 月 20 日 由 颜晋南 在上一篇博文《 ASP.NET MVC5 入门四——添加模型 》中,我们创建了M模型对应的模型类。最终我们还是要在数据库中创建真实的数据库和表,字段等。对于开发人员,数据库在开发过程中只是需要一些简单的功能,为了开发而安装一个企业版的SQL SERVER太浪费了。还好微软在SQL2012中提供了LocalDB这个新特性,LocalDB也是VS2013默认就安装的。 什么是LocalDB简单说就是 SQL免费版的SQL Server Express 的轻量级版本。专门为开发人员创立的,易于安装,无需管理,编程语言和T-SQL语言都和正常的数据库一样。同时不耗费系统支援,没有服务,需要时自动启动停止。其他更高级的功能就不说了,够用,免费,好用才是王道。同时LocalDB数据库也能方便的移植到SQL Server。 添加连接字符串默认情况下,实体框架会查找和对象同名的上下文里面的连接字符串。在项目的根目录下面打开Web.config文件: 默认的连接字符串: 我们在<connectionStrings>里面添加一个新的连接字符串: <add name=”MovieDBContext” connectionString=”Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|Movies.mdf;Integrated Security=True” providerName=”System.Data.SqlClient” /> 可以看出2个连接字符串都很相似。第一个名字是 DefaultConnection 用来控制可以访问该应用程序的成员资格数据库。我们添加自己的Movie.mdf数据库,不使用成员资格数据库。连接字符串的名字必须和DbContext类的名称相匹配。 添加好了之后,就是 下一步:从控制器访问模型中的数据 。 ASP.NET MVC5 入门六——通过控制器访问数据发表于 2013 年 8 月 22 日 由 颜晋南 首先,我们要添加一个新的控制器,在解决方案资源管理器的Controllers文件夹右键单击,添加,支架。 在对话框中,我们选择下图这个: MVC5 控制器带有 读/写 和 视图。 名字就叫做:MoviesController 。model class 选择 MVC5DEMO.Models里面的 Movie。 数据上下文选择 我们的MovieDBContext。然后点击ADD。 恩,悲剧了。我们重新修改Models\Movie.cs文件,把Movies 改成Movie。 然后ASP.NET MVC5将会自动创建增删查改(CRUD)的方法(action)和视图(views)。是的,一个完整功能的网站就OK了。我们F5运行看看。 当然,没有数据,因为我们没有添加任何数据。接下来我们点击 Create New 添加新的电影条目。 添加电影:我们来看看代码我们刚才添加一个新的controller的那个操作,系统自动添加了哪些文件?
显然,视图(movies)里面的那些个 cshtml 文件对应着增删改查和首页等的页面。我们先来看看 MoviesController.cs里面有什么? 上面的14行,定义了一个私有的电影数据上下文,可以用它来进行查询,编辑,删除等。 第18行的Index()方法返回的是 数据上下文中 所有的电影列表。 强类型和@model关键字前几篇的博文,我们要返回一些到前台是用 ViewBag 来封装一些数据。当时说了 ViewBag 是动态对象,你可以随意添加。我们这次演示的是强类型,除了性能上的优点还有如下优点:在编写代码时候有智能提示;编译时候也能检查代码是否有问题。 在上面代码25行的 Details 方法,它有个ID的参数。ID在我们前面也说过:类似于这里面的那个1就是ID。用来表示电影的序号。当然也可以用 ?id=1 这样来表示。如果找到了对应id的“电影”(27行的代码)就返回 视图(view)同时把movie传进去也就是返回一个强类型的实例。我们看看对应的view(Details.cshtml)里面的代码: 第一行就是一句 @model 指令。这个指令的作用是告诉视图模板,这次传过来的对象是什么类型的,上图例子就是传过来一个 models 里面的movie 对象。这样在details.cshtml里面我们就能通过model.titile拿到movie的标题。 我们再来看看index视图的代码: 这次的 model 是一个实现了IEnumerable 接口的对象。所以我们可以用foreach遍历它: 这又是强类型的一个好处,可以用循环遍历! 我们在web.config里面添加了一串连接字符串,指定Movies的数据库是LocalDB数据库里面的Movies.mdf。我们可以在资源管理器里面查看如下图:如果看不见请单击 显示所有文件 按钮: 双击 Movies.mdf 文件,会打开 服务器资源管理器,然后我们展开 表 看看: 能看到就像以前安装 SQL SERVER一样操作数据库。 简单的介绍就到这里,明显可以看出,开发工具的进步是越来越振奋人心了! 下一步: 优化系统生成的代码 。 ASP.NET MVC5 入门七——完善视图发表于 2013 年 8 月 23 日 由 颜晋南 本节中,我们来修改上一篇博文里面系统自动生成的一些代码,下图是运行后的截图: 可以看到有很多不足比如:英文太多,日期格式太长等。 我们回到 Models\Movie.cs 添加几句代码: 红色框起来的就是增加的部分,using 语句里面的那个 DataAnnotations 我们下载在说。Display 属性指定要显示的字段的名称。原来没有写的话,就是数据库字段的名称,现在我们写上中文了。DataType 指定字段显示的格式,改为日期这样的话时间就不会显示出来,更美观了。 在上图左下角,能看到编辑的链接。这个链接是由 index.cshtml 里面的 Html.ActionLink 方法生成的: Html是个Help 类,调用 ActionLink方法来动态生成HTML超链接。ActionLink方法第一个参数指定显示的字符串,第二个参数是 要调用的Action的名称,第三个参数是一个匿名对象。 按照前几篇讲的 /Movies/Edit/3 和 /Movies/Edit?id=3 是等价的。这2个url都是传递给Movies的Edit方法来去执行,同时给出ID。我们去看看这个方法: 第一个方法是接受GET请求,第二个是接受HttpPost 。可以看到第二个有个属性【HttpPost】而第一个没有,因为默认就是GET请求。我们注意到第二个Edit方法前面还有一个【ValidateAntiForgeryToken】这个主要是用来防止跨站请求伪造(CSRF)。这个需要和视图里面@Html.AntiForgerToken() 配合使用,会生成一个隐藏的防伪标记。下次写个文章介绍一下。 在上面的GET的Edit 方法,调用实体框架的FIND方法查找时候存在对应id的电影,如果存在就返回给视图,不存在就返回404。下面是视图里面的代码: 第一行代码,绑定了一个强类型对象。然后接下来利用这个对象,生成 <label> <input>等代码。Html.LabelFor 这个帮助类的方法显示对应的标题,Html.EditorFor 用来生成<input>标签,Html.ValidationMessageFor 就是用来进行验证的。 生成这么优美的控件,居然一句代码都不用写,真好! 这是表单的源文件,可以看到有个隐藏域,存放着上文的那个 RequestVerificationToken 等信息。从这句话可以看出<form action=”/Movies/Edit/2″ method=”post”>当我们点击save后,表单的所有数据都将用post请求发送到 /movies/edit/2 这个url。 回过头来看POST请求的EDIT方法: 第一步,判断表单中的模型所有属性时候都可以修改或者更新。如果是有效的,就把实体框架状态改为修改,然后更新到数据库。保存之后,重定向到Index 这个方法,我们就会看到修改后的效果。 ASP.NET MVC5 入门八——添加搜索发表于 2013 年 9 月 10 日 由 颜晋南 添加一个搜索的方法和搜索的视图接下来我们添加搜索功能,可以根据电影的标题搜索。 第一步:更新index窗体在最开始MVC入门说过,MVC一个好处就是关注点分离。当我们需要修改和数据有关的东西,只要去修改Controller 就可以。现在我们去修改MoviesController的Index方法: 第一行的LINQ查询用来选择Movies。仅仅是定义了movies代表数据库中的哪些,还没有开始查询。接下来判断查询的字符串是否为空,如果不为空就开始查询标题一样的电影。 s => s.Title 这是一个Lambda 表达式。一般用在基于方法的LINQ查询中,比如上面的Where。 我们现在F5运行一下看看,在地址栏后面加上?searchString=中国 当然,我们不能让用户一直在地址栏加上那么一串来搜索,普遍做法是,在页面顶部加一个搜索框。看到这个就知道需要改动View部分。我们打开Views\Movies\Index.cshtml 文件,在Create New后面加上如下代码: 可以发现,我们并没有添加控制器中Index的POST请求,也能正常查询。我们现在添加HttpPost方法 我们会发现,GET和POST请求的url都是一样的,都是 localhost:xxx/Movies/Index 。假如我们想要把链接发给朋友,让他知道我想看哪些电影,但是这些查询信息却没有在url里面体现,这样不肯能发送给朋友。 解决方法是利用 BeginForm 的重载,有个指定POST请求添加搜索信息到url中。 @using (Html.BeginForm(“Index”,”Movies”,FormMethod.Get)) 改成如上的代码,就可以指定用GET方法提交,哪怕你已经有了HttpPost 的方法。 接下来:添加更多搜索把刚才测试的Index HttpPost 方法删除,我们接下来添加一个功能,让用户可以按照类型来搜索电影。同样是修改Index的方法。代码如下:
第三行的代码,我们添加了一个List对象来保存从数据库取出的电影类型数据。第四行代码是一个LINQ查询。第五行代码我们把获得查询结果存到LIST里面,用了 Distinct 方法,过滤重复对象。 控制器的代码搞定后,就是修改View,在添加一个搜索框。 添加的 @Html.DropDownList(“movieGenre”,”All”) 其中的参数 moiveGenre 会去 ViewBag 里面查询时候存在 IEnumerable<SelectListItem>的参数。在控制器的代码中,我们给ViewBag添加了SelectList参数。 我们运行看看: 可以看出,利用MVC开发网站是非常的方便,快捷。 ASP.NET MVC5 入门九——添加新字段、数据库迁移发表于 2013 年 9 月 17 日 由 颜晋南 在Code First开发中,不可能一开始创建的数据库类就一直不变可能随着需求或者其他原因要做调整。假设我们在原有的Movies里面添加一个评级属性。 然后我们运行下看看。 异常了!注释掉刚才添加的代码,在运行看看: 发现可以访问,这是因为当EF CodeFirst的数据模型发生异动时,默认会引发一个 InvalidOperationException异常。有个解决方法是,在Global.asax 里面的Application_Start方法加上 一个 SetInitializer方法,这个方法会让数据库删除在重新创建。就是因为如此,有了大量的测试数据显然不能用这个方法! 使用Code First数据库迁移首先,我们删除系统自动创建的Movies.mdf文件。如下图,如果在App_Data 里面没有看见,请单击显示所有文件图标。 然后进入(PM)软件包管理控制台 (视图——》其他窗口——》程序包管理控制台)输入以下指令:Enable-Migrations 出现错误那是因为项目中有多个数据类别,所以需要选择一个。重新输入命令:Enable-Migrations –ContextTypeName MVC5DEMO.Models.MovieDBContext 来指定需要迁移的数据库上下文。 好了,我们会发现项目中多了一个文件夹(Migrations)和Configuration.cs文件。 然后我们根据注释的提示,修改下Seed方法的内容为如下:
添加完成后请按下 CTRL-SHIFT-B 生成解决方案 然后我们创建一个数据库迁移的版本,就是初始版本。在管理控制台输入 add-migration Initial 其中Initial可以随便取名。 文件夹下面多了一个日期+Initial.cs 的文件。 接着我们在PM(程序包管理控制台)输入 Update-Database 指令。 这个指令会检测刚才那个cs文件,里面包含数据库的结构的说明,然后运行 Seed里面的方法填充数据。然后我们F5运行看看。 一切正常! 把新属性添加到Model接下来我们给电影模型添加一个分级功能,类似《小时代》少儿不宜!把我们刚刚注释掉的再反注释,然后重新生成下。生成完后还需要修改几个地方,如果你有自己设定Bind属性,还要把新的字段添加进去,同时要去视图修改下。我们去Index.cshtml修改下: 红色框框就是新增加的2处。同样的,Create.cshtml也需要添加。 好了之后我们运行看看。 出现错误了!那是因为现在的模型已经多了一个字段,而数据库还没有变化。可以用上文提到的让系统自动把数据库砍掉在重新生成,或者自己手动修改数据库。不过这些都不是最优的,最好的是使用Code First 的数据库迁移。第一步,更改Seed文件,在默认的那些测试数据中添加分级信息。 然后再PM里面输入 add-migration addRating (名字: addRating 可以随意,最好有意义) 会发现多了一个up和down方法,记录着数据库的变动。接着我们生产解决方案,然后再PM输入:Update-database 命令。然后运行看看: 评级出现了,我们点击 Create New 看看: 一切正常,都能添加。但是这样还不够智能,接下来我们设置自动数据库迁移。 自动数据库迁移在Global.asax里面的 Application_Start方法加上以下代码: 这样以后一旦数据库模型变化,就能自动进行升级。 下一步: 添加验证 。 ASP.NET MVC5 入门十——添加验证发表于 2013 年 11 月 24 日 由 颜晋南 在本教程:将要在Movie 模型添加验证逻辑确保用户添加或者编辑时数据无误。 DRY(不要重复你自己)ASP.NET MVC 的核心设计原则之一就是DRY(Don’t Repeat Yourself)。ASP.NET MVC 鼓励你为一个功能或者行为编码一次,在以后需要用到的地方一直复用就可以。这样可以减少编写代码的数量,同时易于维护。 在ASP.NET MVC 和 EF code first 中提供的验证支持就是DRY的好例子。可以只声明一次,然后在任何需要的地方中执行规则。 向Movie模型中添加验证规则打开 Movies.cs 文件,然后我们来更新Movie类。利用内置的 Required、StringLength、RegularExpression 和 Range Validation 特性添加以下内容: 弄完后,我们看看数据库的设计: 显然和规格不符,我们来修改它。先生成解决方案,接下来就是利用数据库迁移功能自动生成。命令如下:在软件包管理器控制台输入
命令完成时,VS会自动打开一个类文件,我们可以看到其中的Up方法。
Genre 字段不再是可空的,标题和分级都添加了验证条件。我们重新看看数据库的设计: 已经改过来了。相关限制条件在源码里面很清楚了,不在细说。 接下来我们看看效果: 进入 localhost:****/Movies/Create 很明显了,如果没有通过本地客户端的验证,点击Create是不会向服务器提交表单的。 接来下我们看看实现的过程看看在创建视图和创建Action方法时发生了什么 先看看 MoviesController 类中的Create方法: 会发现和以前完全一样,没有任何代码上的变化。第一个Create (GET方法)是用来显示初始创建的窗体。第二个(POST版本的)方法先验证是否有错误(ModelStateIsValid)如果存在错误,则重新显示窗体,否则就在数据库中保存新的电影信息。客户端实现校验是通过 javascript 假如我们禁用它看看会发生什么。禁用方法不同浏览器有不同的选项,搜索一下就可以。 禁用 chrome 后,刷新重新输入: 没错误提示,我们点击Create 很明显,还是有验证,接下来我们输入正确的看看。 成功添加进去了,感兴趣的话,在movie.cs 的 POST Create请求添加断点,会发现输入错误的信息,IsValid 是false ,输入正确是True。 如果你添加了断点测试 启用/禁用 JavaScript 2种情况下Create方法的调用会发现,在启用JS的情况下,如果客户端检测到错误是不会调用Action里面POST的Create方法。如果禁用了JS功能,到表单提交到服务器,会通过 ModelState.IsValid 来验证是否数据存在错误。 下一部分:这次改进了 Create 方法的数据验证,下一次就是 Details 和 Delete 方法了。 感谢作者,祝作者早日创业成功! |
请发表评论