ASP.Net MVC小知识
创建一个ASP.Net MVC Web 应用程序(.NETFramework)
微软文档教程在这里。
ASP.NET MVC使用的是Razor结合的html界面,第一次接触的时候还有点不适应,看了看文档发现跟<%=var%> aspx页面是差不多的,熟悉熟悉Razor语法就可以正常使用了。还是听不难的(为什么不是挺简单…)
这是创建好的MVC项目。
App_Start文件夹里面是一些配置cs文件。
Controllers文件夹里面是控制器,主要语法写在这里。
Models文件夹里面是实体数据模型,与数据库交互的地方。下面有介绍的。
Views文件夹里面是视图文件,也就是HTML(cshtml)文件。
用户通过请求控制器来获得视图里面的内容。
做一个注册页
首先创建一个实体数据库模型(介绍在下面。往下翻)
然后打开HomeController.cs文件,在里面追加一个方法。
public ActionResult Register(){ViewBag.Message = "这是注册页.";return View();}
然后右击方法名,–添加视图
ok,视图就创建好了。视图采用的是默认模板。
打开视图文件,优雅的写上一段form提交模板。写上ajax
<script src="~/Scripts/jquery-3.3.1.min.js"></script><script>$(function () {$("#btnRegister").click(function () {var pars = $("#form1").serializeArray();$.post( "/home/Regist",pars, function(data) {alert(data);});});});</script>//这里呢,是跳转到home控制器下面的Regist方法中。在下面<form method="post" action="/home/Regist" id="form1"><label id="tips"></label>@*把name赋值为usersinfo里的内容*@账号:<input type="text" id="userName" @*name="username"*@ name="uaccount"/><br />密码:<input type="text" id="userPass" @*name="userpass"*@ name ="upassword"/><br />邮箱:<input type="text" id="userEmail" @*name="useremail"*@ name="uemail"/><br />手机:<input type="text" id="userPhone" @*name="userphone"*@ name ="uphone"/><br /><input type="submit" value="注册" /><input type="button" value="异步注册" id="btnRegister" /></form>
然后再HomeController.cs中这么写。
//这就是跳转到的注册方法。//如果表单元素的name属性的值和实体类中的属性的名字保持一致,//那么表单中的数据会自动赋值给实体中的属性//public ActionResult Regist()//{public ActionResult Regist(usersinfo ui){//usersinfo ui = new usersinfo();//ui.uaccount = Request["username"];//ui.upassword = Request["userpass"];//ui.uemail = Request["useremail"];//ui.uphone = Request["userphone"];ui.udatetime = DateTime.Now.ToString();ztest01Entities db = new ztest01Entities();db.usersinfo.Add(ui);if (db.SaveChanges() > 0){return Content("成功");}else{return Content("失败");}}
这样的话,就完成了。
还可以定义重载,用来区分getOrPost请求,这样看起来代码比较清晰。
public ActionResult Register(){ViewBag.Message = "这是注册页.";return View();}[HttpPost]//只能接收post,优先处理post请求public ActionResult Register(usersinfo ui){ui.udatetime = DateTime.Now.ToString();ztest01Entities db = new ztest01Entities();db.usersinfo.Add(ui);if (db.SaveChanges() > 0){return Content("成功");}else{return Content("失败");}//return View();}
MVC小语法
小知识
MVC表示不应该再次编码的HTML字符串@MvcHtmlString.Create(ViewData["usersinfo"].ToString())这样可以让html字符串正确显示初始化页面的时候进行id赋值<li>@Html.ActionLink("用户详情", "UsersInfoView", "UsersInfo",new {id=1},"")</li>//第三个是routeValues ,是用来赋值id的。增删改查代码在下面MVC RouteConfig.cs路由规则的匹配。routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });routes.MapRoute(name: "Default2",url: "{controller}-{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });如果第一个匹配失败,则会匹配第二个..第三个..第N个直到匹配成功如果都匹配失败,则报错。如果第一个匹配成功了,则直接跳出,不会再匹配第二个,即使第二个也是对的
MVC UsersInfoController增删改查 源代码
UsersInfoView.cshtml — UsersInfoController.cs
MVC使用ajax获取json
HTML代码<script src="~/Scripts/jquery-3.3.1.min.js"></script><script>$(function () {$("#btnGet").click(function(){$.post("/Demo/GetList", {}, function (data) {for (var i = 0; i < data.length; i++) {$("#div1").append(data[i].uaccount);}});});});</script><h2>Index</h2><div><input type="button" value="ajax获取数据" id="btnGet" /></div><div id="div1"></div>控制器代码public ActionResult GetList(){ztest01Entities db = new ztest01Entities();//把获得的数据转成list离合List<usersinfo> list = db.usersinfo.Where<usersinfo>(u => true).ToList();//然后反序列化为json返回到前端return Json(list);}
Routing路由
路由的作用:
确定Controller
确定Action
确定其他参数
根据识别出来的数据,将请求传递给Controller和Action
Area区域
Filter过滤器
AOP:面向切口编程
在用户输入网址到显示页面的过程中做一些操作。
Attribute 是属性,可以附加在方法和类上面,用来进行验证public class FilterDemoAttribute : ActionFilterAttribute{public string Messages { get; set; }/// <summary>在执行操作方法之前由 ASP.NET MVC 框架调用。</summary>/// <param name="filterContext">筛选器上下文。</param>public override void OnActionExecuting(ActionExecutingContext filterContext){filterContext.HttpContext.Response.Write("在执行操作方法之前由 ASP.NET MVC 框架调用" +"\n" + Messages);base.OnActionExecuting(filterContext);}/// <summary>在执行操作方法后由 ASP.NET MVC 框架调用。</summary>/// <param name="filterContext">筛选器上下文。</param>public override void OnActionExecuted(ActionExecutedContext filterContext){filterContext.HttpContext.Response.Write("在执行操作方法之后由 ASP.NET MVC 框架调用" + "\n" + Messages);base.OnActionExecuted(filterContext);}/// <summary>在执行操作结果之前由 ASP.NET MVC 框架调用。</summary>/// <param name="filterContext">筛选器上下文。</param>public override void OnResultExecuting(ResultExecutingContext filterContext){filterContext.HttpContext.Response.Write("在执行操作结果之前由 ASP.NET MVC 框架调用" + "\n" + Messages);base.OnResultExecuting(filterContext);}/// <summary>在执行操作结果后由 ASP.NET MVC 框架调用。</summary>/// <param name="filterContext">筛选器上下文。</param>public override void OnResultExecuted(ResultExecutedContext filterContext){filterContext.HttpContext.Response.Write("在执行操作结果后由 ASP.NET MVC 框架调用" + "\n" + Messages);base.OnResultExecuted(filterContext);}}
例如附加在Controller上。
[FilterDemo]public class HomeController : Controller{}
这样Controller里面所有的页面加载之前之后都会进行验证
所以可以把验证的代码写在这里面进行统一的验证,
修改起来也方便。
ASP.Net小知识点(一)
EntityFramework的安装(2020-08-17测试)
第一步:首先下载 (1)和(2)
(1):mysql-connector-net-6.10.7.msi
这个一定要安装这个!!(下面有详细解释)
(2):mysql-for-visualstudio-1.2.8.msi 或者1.2.7 下载
第二步:打开visual studio 2019
新建一个 .net web项目
然后通过 Nuget 安装 MySql.Data.Entity-6.10.7
安装 MySql.Data.Entity-6.10.7 的时候会同步安装其他依赖,所以安装这一个就可以了。一定要和 mysql-connector-net 版本相同。
重点来了,如果 MySql.Data.Entity 的版本和 mysql-connector-net 的版本不一样,而且 mysql-for-visualstudio 这个的版本高于这两个配套得版本时,创建 实体数据模型 的时候就会闪退。
所以,一定要按照这个模板安装。(如果后来更新的话,可以再重新尝试新的搭配。)
在进行连接数据库的时候,这里的 Old Guids 一定要选true 。
然后下面的端口号,如果不是3306的话,就需要填入自己的端口号才能进行连接。

然后选择要操作的表,进行勾选,然后点击完成,就创建完成了。
还有就是本地的mysql在进行这项操作的时候可能会报错,我的就是这样,使用了云数据库以后就不会报错了,网上也查不到,不知道是不是特例。
使用实体数据模型创建MySQL数据表
先创建一个空的实体数据模型。
然后点击新建的数据模型,在空白处右键 — 新增实体

然后给新建的实体添加属性就可以了
当设计好数据表以后,右键这个数据表
点击 根据模型生成数据库。
这里可能会报错,如果报错的话,可能就是生成工具的版本错误了。
点击数据表所在的空白处,右键,选择 -属性
修改DDL生成模板
可能有很多选项,选择一个不会出错的 就可以了。
生成完毕以后,会出现一个sql文件。
如果是SQLserver的话可以直接右键文件–运行
如果是MySQL的话,就需要把这段数据库代码粘贴到数据库查询页面,然后执行。
注意!这里有一段话,是判断是否存在当前数据库的,如果存在就会直接DROP数据库,如果数据库有东西的话,不删除这段话可能会欲哭无泪。。记得删除。
好啦,这样就完成从数据库模型到数据表的转换了。
EntityFramework相关知识
通过Entity向数据库添加数据
//当添加按钮点击时,通过Entity向数据库添加数据protected void Button1_Click(object sender, EventArgs e){var mb = new MemberInfo();mb.mitypeid = 7;mb.miname = "EF我叫EF";mb.miphone = "这是phone";mb.mimoney = 333333;mb.miisdelete = false;//找到 Model1.Context.tt 里的类名,也就是数据表名加上Entities//通过它向数据库添加操作var mtd = new myTestDatabaseEntities();//将数据添加到EF并添加了添加标记。mtd.MemberInfo.Add(mb);//把数据保存到数据库 自动生成语句添加到数据库。//返回受影响的行数 intvar lines = mtd.SaveChanges();//获得刚插入的idResponse.Write(mb.miid);}
通过Entity向数据库查询数据 — linq表达式
//当查询按钮点击时protected void Button2_Click(object sender, EventArgs e){//new 一个数据库操作类myTestDatabaseEntities db = new myTestDatabaseEntities();//使用 Linq 表达式IQueryable<MemberInfo> memberList = from mem in db.MemberInfo where mem.miid == 28 select mem;//遍历得到的数据//延迟加载机制 --当数据使用到的时候,才会进行查询 例子中当语句走到 in 的时候,才开始进行数据库查询foreach (MemberInfo mebInfo in memberList){Response.Write(mebInfo.miphone);}}
通过Entity向数据库删除数据
//当删除按钮点击的时候protected void Button3_Click(object sender, EventArgs e){var db = new myTestDatabaseEntities();//var memberList = from mem in db.MemberInfo// where mem.miid == 28// select mem;////返回第一个元素或者null(没有元素的时候) FirstOrDefault();//MemberInfo mbi = memberList.FirstOrDefault();//if (mbi != null)//{// //删除查出来的数据// //db.MemberInfo.Remove(mbi);// //通过枚举标记数据的状态 标记为删除状态// db.Entry<MemberInfo>(mbi).State = System.Data.Entity.EntityState.Deleted;// //更新到数据库中// db.SaveChanges();//}//else//{// Response.Write("删除的数据不存在");//}//方法2 常用MemberInfo mbi = new MemberInfo(){miid = 29};db.Entry<MemberInfo>(mbi).State = System.Data.Entity.EntityState.Deleted;db.SaveChanges();}
通过Entity向数据库更新数据
//更新按钮点击的时候protected void Button4_Click(object sender, EventArgs e){var db = new myTestDatabaseEntities();var memberList = from mem in db.MemberInfo where mem.miid == 31 select mem;var mbi = memberList.FirstOrDefault();mbi.miphone = "新的phone新的phone";//把状态标记为更新db.Entry<MemberInfo>(mbi).State = EntityState.Modified;db.SaveChanges();}
EntityFramework错误指示
找不到连接字符串
错误:No connection string named ‘XXXXX’ could be found in the application config file.
出现这个错误的原因是因为虽然在类库中的AppConfig里面设定了Entity的连接字符串,但是在主项目中没有这个连接字符串,所以就会报这个错误,只要把连接字符串从类库中复制到主项目的AppConfig里面,就不会报错了。
ASP.Net小知识点(二)
委托Action<>();
if (this.textBox1.InvokeRequired)//是否要对文本框进行跨线程访问。{//Invoke:去找创建TextBox的线程(主线程(UI线程)),有主线程完成委托方法的调用。this.textBox1.Invoke(new Action<TextBox, string>(ShowTextBoxValue), this.textBox1, a.ToString());//}else{this.textBox1.Text = a.ToString();}private void ShowTextBoxValue(TextBox txt, string value){txt.Text = value;}当两个线程共同调用一个方法的时候,可以定义一个公共资源锁。在锁死的时候,其他线程无法进行访问。private void button5_Click(object sender, EventArgs e){// this.textBox1.Text = "safasdfd";Thread thread1 = new Thread(AddSum);thread1.IsBackground = true;thread1.Start();Thread thread2 = new Thread(AddSum);thread2.IsBackground = true;thread2.Start();}private static readonly object obj = new object();private void AddSum(){lock (obj){for (int i = 0; i < 2000; i++){int a = Convert.ToInt32(this.textBox1.Text);a++;this.textBox1.Text = a.ToString();}}}自定义跨线程访问方法private void button4_Click(object sender, EventArgs e){Thread thread1 = new Thread(ShowResult);thread1.IsBackground = true;thread1.Start();}private void ShowResult(){int a = 0;for (int i = 0; i < 600000000; i++){a = i;}//MessageBox.Show(a.ToString());if (this.textBox1.InvokeRequired)//是否要对文本框进行跨线程访问。{//Invoke:去找创建TextBox的线程(主线程(UI线程)),有主线程完成委托方法的调用。this.textBox1.Invoke(new Action<TextBox, string>(ShowTextBoxValue), this.textBox1, a.ToString());//}else{this.textBox1.Text = a.ToString();}}
JSON转义
using Newtonsoft.Json;....var s = JsonConvert.ToString(@"a\b");Console.WriteLine(s);....
web.config

这里的debug在正式上线网站的时候一定要设置为false。
//错误页面配置<customErrors mode="On" defaultRedirect="MyErrorPage.html"><error statusCode="403" redirect="NoAccess.htm" /><error statusCode="404" redirect="FileNotFound.html" /></customErrors>
IsPostBack
IsPostBack 判断是不是post请求
是根据VIEWSTATE隐藏域进行判断的。是post的话,隐藏域的value也会提交
所以属性就是true了。
如果去掉了form的标签 runat 就不能用该属性进行判断了。
因为去掉了runat 就不会有VIEWSTATE隐藏域了。
更新网页信息
替换占位符的内容 重新写入网页中
string filePath = context.Request.MapPath("UserInfoList.html");
string fileContent = File.ReadAllText(filePath);
fileContent = fileContent.Replace("@tbody", sb.ToString());
context.Response.Write(fileContent);
上传文件的时候 form中必须加入这个编码。才能把文件流发送到服务器。
<form action="/Upload.ashx" method="post" enctype="multipart/form-data">
<input type="file" name="fileup" value="" />
<input type="submit" name="submit2" value="提交" />
</form>
mysql实现分页查询
搜索这个表 在第10行往后搜索25个。结果是 11 -35
SELECT * FROM usersInfo LIMIT 10, 25
分25个每页查询
int infoIndex = pages * 25;
StringBuilder sb = new StringBuilder();
if (infoIndex < 25)
{
sb.AppendFormat("select * from usersInfo LIMIT {0},{1}", 0, 25);
}
else
{
sb.AppendFormat("select * from usersInfo LIMIT {0},{1}", (pages - 1)*25, 25);
}
string sqlUrl = sb.ToString();
接受总数据库的行数
string
conUrl=ConfigurationManager.ConnectionStrings["connectStr"].ConnectionString;
string sqlUrl5 = "select count(*) from usersInfo";
MySqlConnection msc = new MySqlConnection(conUrl);
msc.Open();
MySqlCommand mcmd = new MySqlCommand(sqlUrl5, msc);
int counts = Convert.ToInt32(mcmd.ExecuteScalar());
msc.Close();
return counts;
mysql实现联合查询
//联合查询
SELECT mi.*,mti.`memtitle` FROM MemberInfo AS mi INNER JOIN MemberTypeInfo AS mti ON mi.`mitypeid`=mti.`memid`
创建cookie
//创建cookies
//Response.Cookies["ck1"].Value = "123345";
//创建cookie并指定过期时间
Response.Cookies["ck1"].Value = "12334242";
Response.Cookies["ck1"].Expires = DateTime.Now.AddDays(3);
//获取cookie
Response.Write(Request.Cookies["ck1"].Value);
//删除cookie
Response.Cookies["ck1"].Value = "12334242";
Response.Cookies["ck1"].Expires = DateTime.Now.AddMilliseconds(-1);
//cookie跨域
Response.Cookies["ck1"].Value = "12334242";
Response.Cookies["ck1"].Domain = "";//该处设置为主域名
子域名的cookie默认不会发送给主域。
反之则可以。
创建session
//创建session
Session["user"] = userA;
Session["pass"] = MD5Helper.CreateMd5(userP).ToString();
//要在普通类中使用session,要使其继承System.Web.UI.page
//继承之前要先进行引用,然后就可以使用session了。
//因为一个网站会有很多网页,所以每一个网页进行验证session的时候
//要写很多代码,所以可以封装一个验证类。需要验证的时候调用类就行了
//session主要是用来验证登录,存储重要信息的。因为信息存储在web端
//不会造成泄露的风险。
//指定session的过期时间
session默认过期时间是二十分钟。是滑动过期时间。
ashx中使用session
1.命名空间中要加入using System.Web.SessionState;
2.接口名要加入IRequiresSessionState或IReadOnlySessionState;
3.不管是Session还是QueryString都要通过HttpContext来获取。
//统一验证session的方法。
定义一个类继承System.Web.UI.Page
public partial class UniteCheckSession : System.Web.UI.Page
{
public void Page_Init(object sender, EventArgs e)
{
if (Session["userAccount"] == null || Session["userPass"] == null)
{
Response.Redirect("/Login.aspx");
}
}
}
这样就重写了Page_Init方法,继承子类同时也继承父类
所以直接继承子类就行了。就可以在想要的网页中添加验证
session是每个用户特有的。每个用户都有自己的session对象。
但是放在cache里的数据是大家共享的。
创建Cache
创建cache
Cache["thisCache"] = "This is a cache";
Cache.Insert("thisCache","This is a cache",null,DateTime);
如果cache不指定过期时间,那么cache就会一直存在服务器内存中,知道服务器关闭。
cache文件依赖
string filePath = Request.MapPath("File.txt");
if (Cache["fileContent"] == null)
{
//文件缓存依赖.
CacheDependency cDep = new CacheDependency(filePath);
string fileContent = File.ReadAllText(filePath);
Cache.Insert("fileContent", fileContent, cDep);
Response.Write("数据来自文件");
}
else
{
Response.Write("数据来自缓存:"+Cache["fileContent"].ToString());
}
内容类型

这里的text/html要和刷进去的代码样式一样。。不能是plain刷html,不然就写不出代码。
JQuery失效的问题

这个样子是正确引用
这个则是错误引用,是不能操作jQuery的。
