7天玩转 ASP.NET MVC

在开始时请先设置firefox中about:config中browser.cache.check_doc_frequecy设置为1,这样才能在关闭浏览器时及时更新JS

第一、二天的内容与之前的重复,这里不再重复

弱类型ViewData 中的数据类型是Object。所以我们在使用之前需要进行正确的类型转换,没有类型安全

public ActionResult GetView()
{
    Employee emp = new Employee();
    emp.FirstName = "Sukesh";
    emp.LastName = "Marla";
    emp.Salary = 20000;
    ViewData["Employee"] = emp;
    return View("MyView",ViewData);
}

视图

<div>
    @{
        MyWeb.Models.Employee emp =
        (MyWeb.Models.Employee)ViewData["Employee"];
    }
    <b>Employee Details </b><br />
    Employee Name : @[email protected] <br />
    Employee Salary: @emp.Salary.ToString("C")
</div>

强类型

视图中要先@using 项目.models.类型,然后再使用@model  每个视图只有一个model

在这前请理解一下MVVM的模式:

其是把model转变为一个ViewModel再显示给用户

相关代码请查看PDF中的30页Lab 7 - View 中运用Collection

主要代码:

public ActionResult GetView()
{
    EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();//实例化雇员视图列表模型

    EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); //雇员实体模型
    List<Employee> employees = empBal.GetEmployees(); //实体获取数据

    List<EmployeeViewModel> empViewModels = new List<EmployeeViewModel>(); //雇员列表视图模型
    foreach (Employee emp in employees) //把实体模型转换成雇员列表视图模型
    {
        EmployeeViewModel empViewModel = new EmployeeViewModel();
        empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
        empViewModel.Salary = emp.Salary.ToString("C");
        if (emp.Salary > 15000)
        {
            empViewModel.SalaryColor = "yellow";
        }
        else
        {
            empViewModel.SalaryColor = "green";
        }
        empViewModels.Add(empViewModel);
    }
    employeeListViewModel.Employees = empViewModels; //把列表转换至视图列表
    employeeListViewModel.UserName = "Admin";
    return View("MyView", employeeListViewModel); //输出
}

第三天

在wed.config添加连接参数 相关说明 相关说明2

<connectionStrings>
<add name="SalesERPDAL" connectionString="Data Source=(local);Initial Catalog=SalesERPDB;Integrated Security=True"  providerName="System.Data.SqlClient"/>
</connectionStrings>

name为根名称,connectionString的字段设置

  • Data Source 可以Serve代替其值写为计算机名,或.\SQLExpress
  • Initial Catalog 数据库
  • Integrated Security 连接帐号 True表示当前windows帐号,如果为网络连接就应该改为uid=sa;pwd=12345678a.;
  • providerName表示使用的命名空间是"System.Data.SqlClient".而ACCESS则是"System.Data.OleDb".
  • Connect Timeout表示超时秒数 30则30秒

连接数据库实体,类中重写OnModelCreating 方法,DbSet 将会展示所有可以在数据库中查询到的Employees。

public class SalesERPDAL : DbContext
{
    /// <summary>
    /// 用于控制生成表的
    /// </summary>
    /// <param name="modelBuilder"></param>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Employee>().ToTable("TblEmployee");//表名称
        base.OnModelCreating(modelBuilder);
    }
    /// <summary>
    /// 表示上下文中给定类型的所有实体的集合或可从数据库中查询的给定类型的所有实体的集合
    /// </summary>
    public DbSet<Employee> Employees { get; set; }
    public SalesERPDAL():base( "testdb")//这里的testdb对应wed中的configSections名称
    {
    }

}

为Employee 类创建主键

using System.ComponentModel.DataAnnotations;//注意要声明
public class Employee
{
[Key]
public int EmployeeId { get; set; } //设定为主键
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}

设置 EmployeeBusinessLayer.GetEmployees()的方法

public List<Employee> GetEmployees()
{
     SalesERPDAL salesDal = new SalesERPDAL();
     return salesDal.Employees.ToList();
}

GetView()方法请查看上面

验证与提交

在Global.asax加入(数据库初始化,如果模型变更)

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());

视图中加入消息框与提交与取消

这里没有用「input type = reset」控件,因为不会清除值,它只是将控件的值改为默认的值。例如:
<input type="text" name="FName" value="Sukesh">点完reset控件,只会变回默认值,在更新数据时可以用这按钮

在视图中呈现错误

<script>
    function ResetForm() {
document.getElementById(‘TxtFName‘).value = "";
document.getElementById(‘TxtLName‘).value = "";
document.getElementById(‘TxtSalary‘).value = "";
}
</script>
@{

    ViewBag.title = "CreateEmployee";
}
    <div>
        <form action="/Employee/SaveEmployee" method="post">
            <table>
                <tr>
                    <td>
                        First Name:
                    </td>
                    <td>
                        <input type="text" id="TxtFName" name="FirstName" value="" />
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="right">
                        @Html.ValidationMessage("FirstName")
                    </td>
                </tr>
                <tr>
                    <td>
                        Last Name:
                    </td>
                    <td>
                        <input type="text" id="TxtLName" name="LastName" value="" />
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="right">
                        @Html.ValidationMessage("LastName")
                    </td>
                </tr>
                <tr>
                    <td>
                        Salary:
                    </td>
                    <td>
                        <input type="text" id="TxtSalary" name="Salary" value="" />
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="right">
                        @Html.ValidationMessage("Salary")
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <input type="submit" name="BtnSubmit" value="Save Employee" />
                        <input type="submit" name="BtnSubmit" value="Cancel" />
                        <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
                    </td>
                </tr>
            </table>
</form>
</div>

HTML代码

模型相关的验证 相关链接  int?表示可以为空值

  • DataType。确保数据是指定的类型,例如邮箱、信用卡号、URL 等。
  • EnumDataTypeAttribute。确保在Enumeration 中存在该值。
  • Range Attribute。确保值在一个指定的区域内。
  • Regular。认证值是否是指定的表达式。
  • Required。确保值是存在的。
  • StringLength。认证字符串中的最大和最小字符长度。
public class Employee
{
    [Key]
    public int EmployeeId { get; set; }

    [Required(ErrorMessage = "请输入你的名字")]
    public string FirstName { get; set; }
    [StringLength(5, ErrorMessage = "姓不能超过5个字符")]
    public string LastName { get; set; }
    public int Salary { get; set; }

}

控制器的修改

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
        {
            switch (BtnSubmit)
            {
                case "Save Employee":
                    if (ModelState.IsValid)
                    {
                        EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
                        empBal.SaveEmployee(e);
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        return View("CreateEmployee");
                    }
                case "Cancel":
                    return RedirectToAction("Index");
            }
            return new EmptyResult();
        }

多个提交Form

  • 隐藏 Form 元素 视图中通过JavaScript将form提交

    <form action="/Employee/CancelSave" id="CancelForm" method="get" style="display:none">
    </form>
    <input type="button" name="BtnSubmit" value="Cancel" onclick="document.getElementById(‘CancelForm‘).submit()" />
  • 运用 JavaScript 动态地改变动作URL

    <form action="" method="post" id="EmployeeForm" >
    <input type="submit" name="BtnSubmit" value="Save Employee" onclick="document.getElementById(‘EmployeeForm‘).action = ‘/Employee/SaveEmployee‘" />
    ...
    <input type="submit" name="BtnSubmit" value="Cancel" onclick="document.getElementById(‘EmployeeForm‘).action = ‘/Employee/CancelSave‘" />
    </form>
  • Ajax 不再运用 Submit 按钮,取而代之的是简单的输入按钮,然后运用JQuery 或者其它库来实现纯Ajxa 请求。

Model Binder模型绑定的问题 视图转至控制器 相关链接(注:这一节请看相关连接暂不做学习)

类型模型允许为空应该在模型里设置int?类型或设置为string类

public int? Salary{get;set;}

自定义验证新类,然后在模型字段中加入[FirstNameValidation]

public class FirstNameValidation : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null) // Checking for Empty Value
            {
                return new ValidationResult("请输入你的名字");
            }
            else
            {
                if (value.ToString().Contains("@"))
                {
                    return new ValidationResult("名字不应该包含 @");
                }
            }
            return ValidationResult.Success;
        }
    }

第四天保留值

新增一个类,用来存储临时值,类型全为STRING然后在输入有误的过程中设置返回

CreateEmployeeViewModel vm = new CreateEmployeeViewModel();//存储临时值类
 vm.FirstName = e.FirstName; //赋值
 vm.LastName = e.LastName;
 if (e.Salary.HasValue)
 {
     vm.Salary = e.Salary.ToString();//转换为字符存存临时值
 }
 else
 {
     vm.Salary = ModelState["Salary"].Value.AttemptedValue;//显示原始值
 }
 return View("CreateEmployee", vm); // Day 4 Change - Passing e here

客户端验证(注:客户端认证与服务端验证不冲突)

function IsFirstNameEmpty() {
    if (document.getElementById(‘TxtFName‘).value == "") {
        return ‘名字不应该是空的‘;
    }
    else { return ""; }
}
function IsFirstNameInValid() {
    if (document.getElementById(‘TxtFName‘).value.indexOf("@") != -1) {
        return ‘姓不应该包含@‘;
    }
    else { return ""; }
}
function IsLastNameInValid() {
    if (document.getElementById(‘TxtLName‘).value.length>=5) {
        return ‘姓不应该超过5个字符。‘;
    }
    else { return ""; }
}
function IsSalaryEmpty() {
    if (document.getElementById(‘TxtSalary‘).value=="") {
        return ‘工资不应该是空的‘;
    }
    else { return ""; }
}
function IsSalaryInValid() {
    if (isNaN(document.getElementById(‘TxtSalary‘).value)) {
        return ‘输入有效的工资‘;
    }
    else { return ""; }
}
function IsValid() {
    var FirstNameEmptyMessage = IsFirstNameEmpty();
    var FirstNameInValidMessage = IsFirstNameInValid();
    var LastNameInValidMessage = IsLastNameInValid();
    var SalaryEmptyMessage = IsSalaryEmpty();
    var SalaryInvalidMessage = IsSalaryInValid();
    var FinalErrorMessage = "错误:";
    if (FirstNameEmptyMessage != "")
        FinalErrorMessage += "\n" + FirstNameEmptyMessage;
    if (FirstNameInValidMessage != "")
        FinalErrorMessage += "\n" + FirstNameInValidMessage;
    if (LastNameInValidMessage != "")
        FinalErrorMessage += "\n" + LastNameInValidMessage;
    if (SalaryEmptyMessage != "")
        FinalErrorMessage += "\n" + SalaryEmptyMessage;
    if (SalaryInvalidMessage != "")
        FinalErrorMessage += "\n" + SalaryInvalidMessage;
    if (FinalErrorMessage != "错误:") {
        alert(FinalErrorMessage);
        return false;
    }
    else {
        return true;
    }
}

视图中加入

<script src="~/Scripts/Validations.js"></script>
<input type="submit" name="BtnSubmit" value="Save Employee"onclick="return IsValid();" />

添加授权认证

新建控制器Login

在要控制的页面方法前加入[Authorize]属性

如果所有控制器页面都要认证的话,应在App_start的FilterConfig.cs文件中增加一行,注意是增加

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());//Old line
filters.Add(new AuthorizeAttribute());//New Line
}

然后在AuthenticationController附加上AllowAnonymous属性

Web.confing:

<authentication mode="Forms">
      <forms loginUrl="~/Authentication/Login"></forms>
    </authentication>

业务层加入:

public bool IsValidUser(UserDetails u)
{
    if (u.UserName == "Admin" && u.Password == "Admin")
    {
        return true;
    }
    else
    {
        return false;
    }
}

login视图层

@model MyWeb.Models.UserDetails
@{
    ViewBag.Title = "Login";
}

    <div>
    @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
    {
        @Html.LabelFor(c => c.UserName)
        @Html.TextBoxFor(x => x.UserName)
        <br />
        @Html.LabelFor(c => c.Password)
        @Html.PasswordFor(x => x.Password)
        <br />
        <input type="submit" name="BtnSubmit" value="Login" />
    }
</div>

然后控制器

[HttpPost]
        public ActionResult DoLogin(UserDetails u)
        {
            EmployeeBusinessLayer bal = new EmployeeBusinessLayer();//实例业务层
            if (bal.IsValidUser(u))//判定
            {
                FormsAuthentication.SetAuthCookie(u.UserName, false); //为用户提供验证的Cookie,非永久性的
                return RedirectToAction("Index", "Employee");
            }
            else
            {
                ModelState.AddModelError("CredentialError", "无效的用户名或密码");
                return View("Login");
            }
        }

7示例21 在Login页实现客户端的认证

在页面里添加

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

然后页面视图里加入@Html.ValidationMessageFor(x =>x.UserName)用于显示错误信息

第5天

在视图呈现分部视图在Shared文件夹添加Foorer,其视图加入了模板与模型,下面传入模型与调用方法

@{
Html.RenderPartial("Footer", Model.FooterData);//在区域内Razor,这个方法比Partial更快,Partial返回为MvcHtmlString非字符串
 }
@Html.Partial("Footer", Model.FooterData)

实现基于角色的安全性

枚举用户状态UserStatus.cs 并修改逻辑

public enum UserStatus
    {
        AuthenticatedAdmin,
        AuthentucatedUser,
        NonAuthenticatedUser
    }

业务层

public UserStatus GetUserValidity(UserDetails u)
        {
            if (u.UserName == "Admin" && u.Password == "Admin")
            {
                return UserStatus.AuthenticatedAdmin;
            }
            else if (u.UserName == "Sukesh" && u.Password == "Sukesh")
            {
                return UserStatus.AuthentucatedUser;
            }
            else
            {
                return UserStatus.NonAuthenticatedUser;
            }
        }

然后通过DoLogin的方法Session["IsAdmin"] = IsAdmin;设置当前会话的HttpSessionStateBase 对象

FormsAuthentication.SetAuthCookie(u.UserName, false);
Session["IsAdmin"] = IsAdmin;
return RedirectToAction("Index", "Employee");//重定向致...

在视图中调用,返回GetAddNewLink的方法结果

@{
  Html.RenderAction("GetAddNewLink");
 }

GetAddNewLink再通过判定HttpSessionStateBase 对象的bool值决定是否返回显示相关的add代码

public ActionResult GetAddNewLink()
        {
            if (Convert.ToBoolean(Session["IsAdmin"]))
            {
                return PartialView("AddNewLink");
            }
            else
            {
                return new EmptyResult();
            }
        }

过滤器

新建文件夹Filter下新建AdminFilter.cs继承ActionFilterAttribute并重写OnActionExecuting方法

public class AdminFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!Convert.ToBoolean(filterContext.HttpContext.Session["IsAdmin"]))
            {
                filterContext.Result = new ContentResult()
                {
                    Content = "未授权访问指定资源."
                };
            }
        }
    }

在防用URL的方法前加入[AdminFilter]

在方法前加入[ChildActionOnly]该方法表示只能在View中通过Html.Action或Html.RenderAction来使用,不能通过控制器调用

24 处理CSRF攻击

链接  方法前插入[ValidateAntiForgeryToken]

用法:在View->Form表单中:<%:Html.AntiForgeryToken()%>

在Controller->Action动作上:[ValidateAntiForgeryToken]

原理:1、<%:Html.AntiForgeryToken()%>这个方法会生成一个隐藏域:<inputname="__RequestVerificationToken" type="hidden" value="7FTM...sdLr1" />并且会将一个以"__RequestVerificationToken“为KEY的COOKIE给控制层。

2、[ValidateAntiForgeryToken],根据传过来的令牌进行对比,如果相同,则允许访问,如果不同则拒绝访问。

关键:ValidateAntiForgeryToken只针对POST请求。

换句话说,[ValidateAntiForgeryToken]必须和[HttpPost]同时加在一个ACTION上才可以正常使用。

继承

新建BaseViewModel类

public class BaseViewModel
{
public string UserName { get; set; }
public FooterViewModel FooterData { get; set; }//New Property
}

从 EmployeeListViewModel 类中移除UserName 和FooterData 属性,然后让它继承BaseViewModel 类。

然后创建布局页

@using MyWeb.ViewModels
@model BaseViewModel
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@RenderSection("TitleSection")</title>
    @RenderSection("HeaderSection", false)
</head>
<body>
    <div style="text-align:right">
        欢迎你, @Model.UserName
        <a href="/Authentication/Logout">Logout</a>
    </div>
    <hr />
    <div>
        @RenderSection("ContentBody")
    </div>
    @Html.Partial("Footer", Model.FooterData)
</body>
</html>

更改视图页中的 (注意视图模型的基类也要更改哦)

@{
Layout = "~/Views/Shared/MyLayout.cshtml";
}

@section ContentBody{内容,false}表示里的内存是在布局页中 @RenderSection("ContentBody")中显示的(主要用于定位内容的位置),参数false表示不一定要提供,true表示一定要提供

而布局页中的@RenderBody() 表示显示不在指定部分中的页面内容

应用到所有视图_ ViewStart.cshtml文件里添加 Layout = "~/Views/Shared/_Layout.cshtml";

第五天上传

异步:

上传类:

public class FileUploadViewModel:BaseViewModel
{
public HttpPostedFileBase fileUpload { get; set; }//充当类的基类,这些类提供对客户端已上载的单独文件的访问。
 }

视图中:pplication/x-www-form-urlencoded与multipart/form-data的区别是data能以二进制发送,发大文件数据时效率更高

@model FileUploadViewModel
<form action="/BulkUpload/Upload" method="post" enctype="multipart/form-data">
Select File : <input type="file" name="fileUpload" value="" />
<input type="submit" name="name" value="Upload" /></form>

控制器:(异步处理上传文件方法)

public class BulkUploadController : AsyncController
{
 [AdminFilter]
        public async Task<ActionResult> Upload(FileUploadViewModel model)
        {
            int t1 = Thread.CurrentThread.ManagedThreadId;
            List<Employee> employees = await Task.Factory.StartNew<List<Employee>>(() => GetEmployees(model));
          //  List<Employee> employees = GetEmployees(model);
            EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
            bal.UploadEmployees(employees);
            return RedirectToAction("Index", "Employee");
        }
        /// <summary>
        /// 取得上传文件的雇员信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private List<Employee> GetEmployees(FileUploadViewModel model)
        {
            List<Employee> employees = new List<Employee>();
            StreamReader csvreader = new StreamReader(model.fileUpload.InputStream);
            csvreader.ReadLine(); // 假设第一行是头。
            while (!csvreader.EndOfStream)
            {
                var line = csvreader.ReadLine();
                var values = line.Split(‘,‘);//不同值之间采用逗号分隔
                Employee e = new Employee();
                e.FirstName = values[0];
                e.LastName = values[1];
                e.Salary = int.Parse(values[2]);
                employees.Add(e);
            }
            return employees;
        }
}

异常信息显示

wed.confing中修改,这里修改后App_Start 文件夹下的FilterConfig.cs会自动添加Global 级别过滤器,并修改404错误信息

<system.web>
<customErrors mode="On"><error statusCode="404" redirect="~/Error/Index"/></customErrors>

错误页:显示错误信息

@model HandleErrorInfo
Error Message :@Model.Exception.Message<br />
Controller: @Model.ControllerName<br />
Action: @Model.ActionName

控制器:

[AllowAnonymous]  //跳过权限控制器即跳过基于ActionFilterAttribute为基类的方法
public class ErrorController : Controller
{
    // GET: Error
    public ActionResult Index()
    {
        Exception e = new Exception("Invalid Controller or/and Action Name");
        HandleErrorInfo eInfo = new HandleErrorInfo(e, "Unknown", "Unknown");
        return View("Error", eInfo);
    }
}

不同的错误视图:

方法1:在视图中加入

  • [HandleError(View="MyError")]
  • [HandleError(View="DivideError",ExceptionType=typeof(DivideByZeroException))]
  • [HandleError(View = "NotFiniteError", ExceptionType = typeof(NotFiniteNumberException))]

方法2:在过滤FilterConfig.cs里面加入

filters.Add(new HandleErrorAttribute()
{
ExceptionType = typeof(DivideByZeroException),
View = "DivideError"
});
filters.Add(new HandleErrorAttribute()
{
ExceptionType = typeof(NotFiniteNumberException),
View = "NotFiniteError"
});
filters.Add(new HandleErrorAttribute());

异常日志

新增FileLogger类,在LogException输出文本

public void LogException(Exception e)
        {
            File.WriteAllLines("C://Error//" + DateTime.Now.ToString("dd-MM-yyyy mm hh ss") + ".txt",
            new string[] {"Message:"+e.Message,"StackTrace:"+e.StackTrace});
        }

新增EmployeeExceptionFilter类,并继承处理异常的HandleErrorAttribute类的方法,重写OnException,在重写OnException方法时,再去调用运行基类的OnException方法与LogException方法

public class EmployeeExceptionFilter:HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            FileLogger logger = new FileLogger();
            logger.LogException(filterContext.Exception);
            base.OnException(filterContext);//调用基类的方法
        }
  }

修改过滤器配置FilterConfig.cs

filters.Add(new EmployeeExceptionFilter());//移除HandleErrorAttribute异常的方法

注意:C盘Error的目录必须有相应IIS的权限

在OnException方法中添加filterContext.ExceptionHandled = trueg表示已处理异常,不须在呈现默认的错误页

路由

打开/Employee/BulkUpload网页(重复,不再说明)

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Upload",
url: "Employee/BulkUpload",
defaults: new { controller = "BulkUpload", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

请打开的URL更友好如http://localhost:5832/Employee/变为http://localhost:5832/Employee/List

路由里添加routes.MapMvcAttributeRoutes();//添加在routes.IgnoreRoute后面

index方法前加入 [Route("Employee/List")]

方法参数限制

[Route("Employee/List/{id:int}")]
我们可以拥有如下限制。
1. {x:alpha} – 字符串认证
2. {x:bool} – 布尔认证
3. {x:datetime} – Date Time 认证
4. {x:decimal} – Decimal 认证
5. {x:double} – 64 位Float 认证
6. {x:float} – 32 位Float 认证
7. {x:guid} – GUID 认证
8. {x:length(6)} – 长度认证
9. {x:length(1,20)} – 最小和最大长度认证
10.{x:long} – 64 位Int 认证
11.{x:max(10)} – 最大 Integer 长度认证
12.{x:maxlength(10)} – 最大长度认证
13.{x:min(10)} – 最小 Integer 长度认证
14.{x:minlength(10)} – 最小长度认证
15.{x:range(10,50)} – 整型 Range 认证
16.{x:regex(SomeRegularExpression)} – 正则表达式认证

第七天让项目有组织性

添加>新建解决方案(以下)与类库

View And Controller(存放视图与控制器)

  • 迁移之前项目文件,移除解决方案的EntityFramework包.在Global.asax中移除Database.SetInitializer添加

    using BusinessLayer;
    ...
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    BusinessSettings.SetBusiness();

Model(模型)

  • BusinessLayer(业务层) 引用(数据实体层)与(业务实体层)

    public static void SetBusiness()
    {
        DatabaseSettings.SetDatabase();
    }

    )

  • BusinessEntities(业务实体层) 引用System.ComponentModel.DataAnnotations

ViewModel(视图模型)

  • ViewModel(视图模型层) 引用 System.Web
  • 迁移项目文件中的视图模型到视图模型层

Data Access Layer(数据访问层)

  • 类库DataAccessLayer(数据实体层)引用 (业务实体层) 与 (业务层)、并添加EntityFramework包,                                   注意:在数据实体的类中加入using System.Data.SqlClient;
  • 新增类:DatabaseSettings其中包含方法:
    public static void SetDatabase()
    {
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());
    }

原文地址:https://www.cnblogs.com/praybb/p/8321250.html

时间: 2024-11-09 00:46:28

7天玩转 ASP.NET MVC的相关文章

7 天玩转 ASP.NET MVC — 第 7 天

目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 今天是开心的一天.因为我们终于来到了系列学习的最后一节.我相信你喜欢之前的课程,并从中学到了许多. 1. Lab 32 - 让项目有组织性 这个实验确切地讲无关任何新的功能.它只是使项目更有结构性和系统化. 第一步:创建解决方案文件夹 右击解决方案,然后选择 Add -> New Solution Folder. 将文件夹的名称改为「View And Controller」.现在重复这个步骤,创

7 天玩转 ASP.NET MVC — 第 1 天

0. 前言正如标题「7 天玩儿转 ASP.NET MVC」所言,这是个系列文章,所以将会向大家陆续推出 7 篇.设想一下,一天一篇,你将从一个愉快的周一开始阅读,然后在周末成为一个 ASP.NET MVC 开发者,这很酷吧! 7 天玩儿 转 ASP.NET MVC — 第 1 天 第一天是热身运动,这篇我们将围绕 Controller 和 Views 实践两个 Labs.在每个 Lab 之中都伴随着一些 Question 和 Answer.所以文章的主体框架是 Lab 和 Q&A. 7 天玩儿

7 天玩转 ASP.NET MVC — 第 2 天

0. 前言 我相信在开始第 2 天的学习时,你已经顺利地完成了第 1 天的课程. 我们回顾一下第 1 天的主要关注点: 为什么选择 ASP.NET MVC ? ASP.NET Webforms 和 ASP.NET MVC 的对比 理解 ASP.NET MVC 的 Controller 以及 Views 提醒:如果你还没有完成第 1 天的学习,最好先确保完成它.我们的目标是在最后一天用最佳实践和最新技术方法来创建一个小的 MVC 项目.每一天的 Lab 训练中,我们都会比之前一天增加一些实用性的功

7 天玩转 ASP.NET MVC — 第 5 天

目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第五天的学习.希望第一天到第四天的学习,你都是开心的. 1. Lab 22 - 增加 Footer 在这个实验中,我们将会向 Employee 页面添加 Footer.本次实验的目标是理解分部视图(Partial Views). 什么是「Partial Views」? 逻辑上讲,分部视图(Partial Views) 是一个可重用的视图,它不会被直接显示.它会被其它视图所包含,然后作为该

7 天玩转 ASP.NET MVC — 第 4 天

目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第四天的 MVC 系列学习中.如果你直接开始学习今天的课程,我强烈建议你先完成之前的学习内容再来到这里. 1. Lab 15 - 认证错误的保留值 在 Lab 13 中,我们介绍了服务器端的认证,并且在 Lab 14 中,我们通过添加自定义认证的方式将其提示到一个新的层级. 我强烈建议你再回顾一下 Lab 14.再次执行应用,并且能够很好地理解代码以及输出. 在 Lab 15 中,我们将

玩转Asp.net MVC 的八个扩展点

MVC模型以低耦合.可重用.可维护性高等众多优点已逐渐代替了WebForm模型.能够灵活使用MVC提供的扩展点可以达到事半功倍的效果,另一方面Asp.net MVC优秀的设计和高质量的代码也值得我们去阅读和学习. 本文将介绍Asp.net MVC中常用的八个扩展点并举例说明. 一.ActionResult ActionResult代表了每个Action的返回结果.asp.net mvc提供了众多内置的ActionResult类型,如:ContentResult,ViewResult,JsonRe

7 天玩转 ASP.NET MVC — 第 3 天

目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 我们假定你在开始学习时已经阅读了前两天的学习内容.在第 2 天我们完成了关于显示 Employees 列表的项目. 在第三天,我们将会通过介绍数据访问层和数据入口将它升级到一个新的层次. 1. 数据访问层 在真实场景的项目中,如果没有 Database,那么这个项目是未完成的.在我们的项目中,我们还没有谈到数据库.第三天的首个 Lab 将会学习数据库和数据库层. 这里我们将使用 SQL Serv

7 天玩转 ASP.NET MVC — 第 6 天

目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第六天的 MVC 系列学习中.希望你在阅读此篇文章的时候,已经学习了前五天的内容,这也是第六天学习的前提条件. 1. Lab 27 — 添加批量上传选项 在这个实验中,我们将会创建一个选项,用于从 CSV 文件中上传多个 Employees. 我们将会做两件事. 1. 学会如何运用文件上传控件. 异步控制器. 第一步:创建 FileUploadViewModel 在 ViewModels

ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL

http://www.cnblogs.com/John-Connor/archive/2012/05/03/2478821.html 引言-- 在初级篇中,我们介绍了如何利用基于ASP.NET MVC的Web程序中的Global文件来简单的重写路由.也介绍了它本身的局限性-依赖于路由信息中的键值对: 如果键值对中没有的值,我们无法将其利用凑出我们想要的URL表达式. 初级篇传送门:使用Global路由表定制URL   在进阶篇中,我们将介绍ASP.NET 路由相关类的基类-抽象类RouteBas