C#核心代码片段

浏览器地址框输入域名并回车,通过DNS解析找到对应的IP地址,然后通过HTTP协议建立链接,找到目标服务器位置,接着就是TCP三次握手建立可靠链接,发送数据,服务器处理数据,TCP四次挥手断开链接,最后浏览器根据返回的数据解析渲染呈现页面。

SLOID原则

单一职责原则(SRP原则)

高内聚,低耦合

开放封闭原则(OCP原则)

封闭修改,开放拓展

里斯替换原则(LSP原则)

子类替换父类,实现多态

接口隔离原则(ISP原则)

使用专用小接口

依赖倒置原则(DIP原则)

高层调用接口,底层实现接口

对象变量赋值,判断,装箱

public override bool Equals(object obj){//重写父类equal方法,引用类型不是数据内容的比较,重写GetHashCode方法。

if(obj==null){

return false;

}

else{

if(obj is MyClass){

return this.value==(obj as MyClass).value;

}

}

return false;

}

继承

Parent p=new Child();

Console.WriteLine(p.value);//调用的父类的对象

Console.WriteLine((p as Child).value);

接口与回调

新写一个类实现ICallBack接口,然后将其加入到Controller对象的内部集合

static void Main(string[] args){

Controller controller=new controller();

controller.AddCallBack(new CallBackClass());//CallBackClass实现了ICallBack接口

controller.Begin();

}

class CallBackClass:ICallBack{

Console.WriteLine(DateTime.Now.ToString());

}

多态

继承多态基于抽象类和抽象方法

abstract class Fruit{

public abstract void GrowInArea();

}

FeedAnimals(IEnumerable ans)

对象注入的构造方式

class B{

}

class A{

private B innerobj;

public A(B obj){

innerobj=obj;

}

}

基于接口的对象注入

interface MyInterface{

}

calss B:MyInterface{

}

class A{

private MyInterface innerObj;

public A(MyInterface obj){

innerobj=obj;

}

}

A obj=new A(new B());

1、泛型

属性

private int age;

public int Age{

get{return age;}

set{

if(age

age=18;

else

age=value;

}

}

相较于传值为object的方法

public static SayHi(T tparameter) where T:people  //类型约束

{Console.WriteLine(tparameter.SayHi());

}

public static SayHiObject(object tparameter)

{Console.WriteLine(tparameter);

}

泛型约束

类型后添加

where T:class ,new() //默认是个类,有构造函数

where T:class //引用类型 默认null

where T:struct //值类型

new() //含有无参构造函数

//具体类型,或该类型的子类

Set() 调用T对应的数据实体

1.1序列化

[Serializable]//使类支持序列化

class CollegeStudent{

public string Name="空";

public bool IsMale=true;

}

private void SeriallizeObj(String FileName,CollegeStudent stu){

//创建FileStream对象

using(FileStream writer=new FileStream(FileName,FileMode.Create)){

//创建格式化器对象

IFormatter formatter=new BinaryFormatter();

//格式化器对对象使用FileStream对象序列化对象

formatter.Serialize(writer,stu);

MessageBox.Show("对象成功保存到文件:"+FileName);

}

}

//大批量的复制对象反序列化

MyClass obj=new MyClass();

//创建内存流对象

using(MemoryStream ms=new MemoryStream){

IFormatter formator=new BinaryFormatter();

//对象序列化到内存流

formator.Serialize(ms,obj);

//克隆100个对象

for(int i=0;i

//回到流开头

ms.Seek(0,SeekOrigin.Begin);

//反序列化对象

obj=(formator.Deserialize(ms) as MyClass);

obj.Index+=i;

Console.WriteLine("对象{0}已处理",obj.Index);

}

}

2、反射

便于代码配置

strig IHelperConfig=ConfigurationManager.AppSettings["IHelperConfig"]

Assembly assembly=Assembly.load(IHelperConfig.split(',',0));//动态加载dll

Module[] modules=assembly.GetModules();//取dll所有命名空间

Type[] types=assembly.GetTypes()//取dll所有类

Type typeHelper=assembly.GetType(IHelperConfig)//根据命名空间.类名获取类名

object oHelper=Activator.CreateInstance(typeHelper,false)//根据类名获取对象实例,后面参数为是否调用private构造函数

IHelper iHelper=(IHelper)oHelper;//强转类型为继承的接口,以便调用接口方法

iHelper.Query();

public class SalserverHelper:IHelper{

public void Query(){

Console.WriteLine("1");

}

}

public interface IHelper{ //接口

void Query();

}

//获取方法

foreach(MethodInfo method in typeHelper.GetMethods()){

Console.WriteLine(method.Name);

}

MethodInfo Query=type.GetMethod("Query",new Type[]{typeof(int)});//根据具体方法名称

Query.Invoke(iHelper,null);

//调用私有方法

Methodinfo show1=type.GetMethod("Show1",BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);//构造,公开,非公开

//属性赋值

foreach(var prop in type.GetProperties()){

if(prop.Name.Equals("ID")){

prop.SetValue(iHelper,12); //赋值

}

Console.WriteLine(prop.GetValue(iHelper)); //取值

}

例)

实体类

Public class user:BaseModel{

public string Name{set;get;};

public string ID{set;get;}

}

Public class DBHelper:IDBHelper{

Private static string ConnectionStringCustomers=ConfigurationManager.ConnectionStrings["Customs"].ConnectionString;

Public DBHelper(){

//构造函数

}

public T QueryDomain(){

Type type=typeof(T);

string colunms=string.Join(",",type.GetProperties().Select(p=>string.Format("[{0}]",p.Name)));

string sql=string.Format("select {0} from {1} where id={2}",colunms,type.Name,id);

using(SqlConnection conn=new SqlConnection(ConnectionStringCustomers)){

SqlCommand command=new SqlCommand(sql,conn)

conn.open();

SqlDataAdapter reader=command.ExcuteReader(CommandBehavior.CloseConnection)//自动关闭

if(reader.Read()){

foreach(var prop in type.GetProperties()){

string propertyName=prop.Name;

prop.SetValue(t,reader["propertyName"]);

}

}

}

}

}

2.1、抽象类,接口

抽象类 //类只能被继承一个

public abstract class BasePhone{//描述是什么

Public int Price{get;set;}

public void call(){}

public abstract void system(){}//由于存在未实现的方法,不能被实例化

}

接口 //接口能被实现多个

public interface IPhoneExtend{ //描述做什么

void Pay();

}

3、委托

委托与类同级

private delegate int MyDelegate(string id);声明委托

MyDelegate myDelegate=new MyDelegate (SayHi);//委托实例化

myDelegate+=SayHi;

myDelegate-=SayHi;//方法执行,但是只返回最后一次执行的值

myDelegate()或者myDelegate.Invoke//委托实例调用

委托逻辑分离,去耦合,便于拓展

pravite delegate  string MyDelegate(string id);

public string SayHi(string a){

if(a=="1"){

return “逻辑1”

}else

return “逻辑2”

}

public string DelegateSayHi(string method,Delegate myDelegate){

myDelegate(method);

}

public string SayHi1(){

return “逻辑1”;

}

public string SayHi2(){

return “逻辑2”;

}

总结:代码增多,但去掉方法间关联,便于拓展

4、事件

public event EventHander Click;//事件为一种特殊委托

Click事件的响应方法必须符合EventHander委托的要求:

public delegate void EventHander(Object sender,EventArgs e)

form窗体中实现切换text焦点

foreach(Control ctl in groupBox1.Controls){

if(ctl is TextBox){

(ctl as TextBox).KeyDown+=this.EnterToTab;//委托挂接事件

}

}

private void EnterToTab(Object sender,EventArgs e){

TextBox txt=null;

if(e.KeyCode==Keys.Enter){

groupBox1.SelectNextControl(sender as Control,true, true, true, true);

txt=(sender as TextBox);

if(txt!=null){

txt.SelectAll();

}

}

}

protected override void onClick(EventArgs e){

base.OnClick(e);

ClickCount++;

//激发自定义事件

if(MyClick!=null){

MyClick(this,new MyClickEventArgs(ClickCount));

}

}

组件化开发

1、重用已有组件

2、开发部分新组件

3、组合新旧组件搭建新系统

代码风格

毛病

1、重复代码(同样的代码重复出现,不同代码完成同一功能)

2、过长函数

3、过大的类(明确各类的职责,一个类拆分多个独立的类,采用继承,公有代码移到基类)

4、过多的参数(改为传送对象)

5、原子弹的链式反应(类之间耦合性太强,类实现的功能太多,降低底层数据库变化对上层的影响)

6、曝光隐私(避免暴露内部数据结构,内部具体算法,仅公开必要职责)

7、乱起名字(命名要易于理解,劲量用英语,名字可以很长)

糟糕的设计

1、代码写死文件读取路径

2、UI控件设定底层数据源字段名

3、数据表新增字段,导致N处要修改

脆弱的设计

无法重用的设置

过于复杂的设计

DRY原则-老路不走两遍

KISS原则-绝不画蛇添足

KISS原则-简单即美

DDIY原则-不要一切自己动手

private void Init(){

InitUIControl();

setEventHandler();

}

private void InitUIControl(){//统一控件初始化

txtNum.Text="o";

}

private void setEventHandler(){//统一设置事件响应代码

EventHandler calculateEventHandler=()=>{Calculate();}

txtNum.TextChanged+=calculateEventHandler;

}

public void Calculate(){//公用算法放公共类

...

}

重构改进软件内部结构

软件测试(黑盒&&白盒)

单元测试,功能测试,集成测试,场景测试,系统测试,压力测试

基于职责设计类

命令方法和查询方法

5、Lambda表达式//匿名方法

public delegate  void NoReturn(int x,int y);//无法返回值委托

public delegate int WithReturn(int x);//有返回值委托

public static void Show(){

1)无返回值委托

NoReturn method1=new NoReturn(

delegate(int x,int y)//匿名方法{

console.writeLine("delegate");

}

)

NoReturn method2=new NoReturn(

(int x,int y)=>{

console.writeLine("delegate");

}

)

NoReturn method3=new NoReturn(

( x, y)=>{//委托严格现在了取值类型

console.writeLine("delegate");

}

)

NoReturn method4=new NoReturn(

( x, y)=>console.writeLine("delegate")//如果方法体只有一行,可以去掉大括号和分号

)

2)有返回值委托

WithReturn method5=(x)=>{return 1;};

WithReturn method6=x=> 1;

Action act1=()=>{};//接收0到16个无返回值委托

Action act2=(x,y,z)=>Console.WriteLine("")

}

Func fun1=()=>1//接收0到16个带返回值委托

Funcfun2=(x,y,z)=>z.ToString();

集合查询拓展方法

筛选

IEnumerable nums=IEnumerable.Range(1,100);

var numList=num.Where((num)=>num%5==0);

投影与转换

var fileList=Directory.GetFiles("c:\\","*.*");

var files=fileList.Select(

files=>new FileInfo(file)); //找出C盘根目录所有文件,lambda表达式把string转换为FileInfo对象

var infos=files.Select(info=>new {FileName=info.Name,

FileLength=info.Length //取出FileInfo对象的文件名和文件大小属性

});

排序

OrderBy(升序)或OrderByDescending(降序)

var fileList=Directory.GetFiles("c:\\","*.*").Select(file=>new FileInfo(file))

.OrderByDescending(fileInfo=>fileInfo.Length);

综合(分页)

var pageData=dbContext.UserInfo.where(u=>u.ID>0)

.OrderByDescending(u=>u.ID)//降序

.Skip(5*(3-1))//一条5页,取第三页

.Take(5);

LINQ(表达式返回值实现了IQueryable)

//初始化了IQueryable接口里的三个参数

1、Linq表达式转换成Expression类

2、给Type ElementType赋值

3、给IQueryProvider Provider赋值,ef provider

当用到IQueryable接口集合数据的时候,provider解析Expression然后获取相应数据,进行遍历执行

//1.指定数据源

var number=new int[](0,1,2,3)

//2.创建查询表达式

var numQuery=

from num in numbers //from指定数据源

where (num%2)==0 //where指定筛选器

select num; //select指定返回元素类型

//执行查询

foreach(int num in numQuery){

Console.write("{0}",num);

}

技巧:

1、IEnumerable files=

from fileName in Directory.GetFiles("C:\\")

where File.GetLastWriteTime(fileName)

Path.GetExtension(fileName).ToUpper()==".TXT"//使用C#的运算符和方法

select new FileInfo(fileName);//动态创建新对象

2、混用LINQ与拓展方法

var methods=(from method in members

select method.Name).Distinct();

3、orderby

Enumerable files=

from fileName in Directory.GetFiles("C:\\")

orderby (new FileInfo(fileName)).Length,

fileName ascending

select fileName ;

4、使用部分数据

var files=from fileName in Directory.GetFiles("C:\\")

select new{

Name=fileName,

Length=new FileInfo(fileName).Length //封装成新的匿名对象 (只读)

}

5、引入范围变量暂存数据

Enumerable files=

from fileName in Directory.GetFiles("C:\\")

let file=new FileInfo(fileName)

orderby file.Length,

fileName ascending

select file ;

6、在LINQ中直接调用本地方法

var queryEvenNums=

from num in numbers

where IsEven(num)//C#方法

select num;

分组:

var studentQuery=from student in students

group student //分组中的单个数据key

by student,city //分组依据

foreach(var studentGroup in studentQuery){//第一层循环,遍历每个组

Console.WriteLine("在{0}学生清单:",studentGroup.Key);

int count=0;

foreach(Student stu in studentGroup ){//第二层循环,遍历组中元素

count++;

Console.WriteLine("{0}:{1}:{2}",count,stu.Name,stu.City);

}

}

//into字句对分组进一步处理

var wordGroups=

from w in words

group w by w[0] into grps//引用分组结果

where (grps.Key=='a'||grps.Key=='e'||grps.Key=='o')

select grps;

//实现非此即彼分组,多段分组

var studentQuery=from student in students

group student

by GroupKey(student.Scores) //分组方法

XML

XML文档的查询

使用XPath查询XML文档(例: /books/book[price>50]/price)

XML文档的转换

XML通过XSLT转换为HTML

LINQ to XML

XElemet elem=new XElemet("ElemetName ","ElemetValue")//新建

elem.SetAttributeValue("AttributeName","AttributeValue");//设置修改属性,删除为设置值为null

//XElement的Attributes方法可以获取所有属性集合

foreach(var attr in elem.Attributes()){}

构建xml树

1)XElement Grandparent=new XElement("GrandParent",

new XElement("Parent",

new XElement("Me",

new XElement("Son"),new XElement("Daughter"))));

  1. 2)XElement elem=new XElement ("ElementName",

new XAttribute("attributeName","attributeValue"),//添加属性

new XElement("Child","ChildValue")//添加子元素

);

3)string[] childs=new string[]{"child1","child2","child3"};

XElement elem=new XElement ("Parent",

from str in childs

select new XElement(str)

);

string xmlstr="";//字符串创建xml

XElement xmlTree=XElement .Parse(xmlstr);

xmlTree.Save("tree.xml")//保存xml文件

XElement xmlTree=XElement .Load("tree.xml")//装载xml

查询和访问xml中节点

var elems=from elem in xmlTree.Descendants()

let name=elem.Attribute("Name")

where Startswith(name,"M")

select elem;

修改xml树

XElement Root=new XElement("Root");

Root.Add(from dir in Directory.GetDirectories(@"c:\")

select new XElement("Dir"+(++counter),dir);

删除节点

var childToBeDeleted=new List();

foreach(var child in root.Elements()){

counter++;

if(counter%2!=0){

childToBeDeleted.Add(child);

}

}

childToBeDeleted.ForEach(node=>node.Remove());

PLINQ

var source=Enumerable.Range(1,100);

var evenNums=from num in source.AsParalle()

where num%2==0

select num;

AsSequential

var query=students.AsParallel().where(student=>student.Score>60)//使用并行查询,分数大于60

.OrderByDescending(stu=>stu.Score)//按成绩降序排序

.AsSequential()//强制转换为串行执行

.Select(studentInfo=>

new{

TempID=++counter,//名次

studentInfo.Name.

studentInfo.Score

}

);

AsOrdered

var parallelQuery=

from num in source.AsParallel.AsOrdered()

where num%2==0

select num;

var First10Numbers=parallelQuery.Take(10);

AsSequential()强制PLINQ查询以串行方式执行,而AsOrdered()仍是并行执行,只不过并行执行的结果先被缓存起来,然后再按原始数据顺序排序

Aggregate自定义聚合函数

PLINQ任务取消

CancellationTokenSource cts=new CancellationTokenSource();

//在另一个线程中取消操作

Task.Factory.StartNew(()=>{

CancelPLINQ(cts);

})

//在主线程中启动并行查询

int[] results=null;

try{

results=(from num in source.AsParallel()

.WithCancellation(cts.Token)

where num%3==0

orderby num descending

select num).ToArray();

}

catch(OperationCanceledException e){

Console.WriteLine(e.Message);

}

static void CancelPLINQ(CancellationTokenSource cts){

Random rand=new Random();

Thread.Sleep(rand.Next(150,350));

cts.Cancel();

}

6、异步

private void DoSomething(string name){

Stopwatch watch=new Stopwatch();

watch.Start();

Console.WriteLine("这里是name={0},当前线程ID={1}",name,Thread.CurrentThread.ManagedThreadId);

long Result=0;

for(int i=0;i

Result+=i;

}

Thread.Sleep(1000);

watch.Stop();

Console.WriteLine("这里是name={0},当前线程ID={1},计算结果{2},耗时{3}",name,Thread.CurrentThread.ManagedThreadId,Result,watch.ElapsedMilliseconds);

}

//同步

private void btnSync_Click(object sender,EcentArgs e){

console.WriteLine("****btnSync_Click******");

for(int i=0;i

string name=string.Format("btnSync_Click_{0}",i);

DoSomething(name);

}

console.WriteLine("****btnSync_Click******");

}

//异步   (主线不需等待子线)

private void btnAsync_Click(object sender,EcentArgs e){

console.WriteLine("**** btnAsync _Click******");

for(int i=0;i

string name=string.Format(" btnAsync _Click_{0}",i);

Action Ac= DoSomething ;

AsyncCallback Callback=>Console.WriteLine("这里是AsyncCallback,AsyncState={0} ",t.AsyncState),"xyz");

IAsyncResult result= Ac.BeginInvoke(name,t=>Console.WriteLine("这里是AsyncCallback,AsyncState={0} ",t.AsyncState));

}//回调

主线等待子线结束的方式

1、result.AsyncWaitHandle.WaitOne(-1);

2、while(!result.IsCompleted){

Thread.Sleep(100);

}

3、

method.EndInvoke(result);

console.WriteLine("**** btnAsync _Click******");

}

理解await的作用

1、static async void TestAsyncInvokeUseAwait(){

Console.WriteLine("DoLongJob方法正在后台执行...");

await DoLongJobUseTask();

Console.WriteLine("DoLongJob方法执行完毕");

2、static void TestAsyncInvokeUseTPL(){

Console.WriteLine("DoLongJob方法正在后台执行...");

Task.Run(()=>DoLongJob())

.ContinueWith(

(task)=>{Console.WriteLine("DoLongJob方法执行完毕");}

)

}

async与线程

7、多线程

//多线程

private void btnThreads_Click(object sender,EventArgs e){

console.WriteLine("****btnThreads_Click******");

List threadList=new List();

for(int i=0;i

Thread thread=new Thread(()=>TestThread("Threads"));

threadList.Add(thread);

thread.Start();

}

threadList.ForEach(t=>t.Join());

console.WriteLine("****btnThreads_Click******");

}

//线程池

private void btnThreadPool_Click(object sender,EventArgs e){

console.WriteLine("****btnThreadPool_Click******");

using(ManualResetEvent m1=new ManualResetEvent(false)){//计时

ThreadPool.QueueUserWorkItem(t=>TestThread("ThreadPool");m1.Set(););

ThreadPool.QueueUserWorkItem(t=>TestThread(t.ToString()),“ThreadPool”);

}

m1.WaitOne();//使用等待句柄阻止主进程终止

console.WriteLine("****btnThreadPool_Click******");

}

//Parallel并行执行

1、Parallel.Invoke(

()=>DoWork1(),

()=>DoWork2()

);

//并行循环

2、Parallel.For(0,100,(i)=>DoWork(i));

//Foreach

3、Parallel.ForEach(sourceCollection,item=>Process(item));

//Task

Task t=new Task(

()=>{//任务方法代码

}

);t.Start();

.Net4.5后推荐使用Task.Run()

Task t=Task.Run(

()=>{任务方法代码}

);

Task t=Task.Factory.StartNew(

()=>{任务方法代码}

)

Task.Delay(5000).Wait();

取回线程运行结果

1) Functiondel=(end)=>{

long sum=0;

for(int i=1;i

sum+=1;

return sum;

};

Task tsk=new Task(del,1000000);

tsk.Start();

Console.Write("程序运行结果为{0}", tsk.Result);

2)Action GetResult=(finishedTask)=>{

if(finishedTask.isFaulted){

Console.Write("程序运行发生异常:{0}", finishedTask.Exception);

}else{

Console.Write("程序运行结果为{0}", finishedTask.Result);

}

}//创建并行处理数据任务对象

Task tskProcess=new Task(ProcessData,1000000);

//数据处理结束时,字段启动下一个工作任务

Task tskGetResult=tskProcess.ContinueWith(GetResult);

//开始并行处理数据

tskProcess.Start();

Task之间的关联与相互协作

Task.Run(()=>DoStep1()).ContinueWith(

(PrevTask)=>DoStep2()

);

父子任务

Task tskParent=new Task(()=>{

//父任务完成的工作

//创建后续子任务并自动启动

Task.Run(...);

Task.Run(...);

})

//启动父任务

tskParent.Start();

父任务等待子任务结束再继续执行

方法一:Task tskParent=new Task(()=>

{

//父任务完成的工作

//创建后续子任务并自动启动

Task child1=Task.Run(()=>{

Task.Delay(1000).Wait();

});

Task child2=Task.Run(()=>{

Task.Delay(1000).Wait();

});

Task.WaitAll(child1,child2);

}

)

方法二:Task tskParent=Task.Factory.StartNew(()=>{

Task tskParent=Task.Factory.StartNew(()=>{

//父任务完成的工作

//创建后续子任务并自动启动

var child1=Task.Factory.StartNew(()=>{

Task.Delay(1000).Wait();

},TaskCreationOptions.AttachedToParent);

var child2=Task.Factory.StartNew(()=>{

Task.Delay(1000).Wait();

},TaskCreationOptions.AttachedToParent);

})

})

任务之间相互等待

Wait:等待单个任务的完成 例: Task t=Task.Run(...);...;t.Wait();

WaitAll:等待一组任务的全部完成

Task t1=Task.Run(...);Task t2=Task.Run(...);...;Task.WaitAll(t1,t2);

WaitAny:等待一组任务的任何一个任务完成

Task t1=Task.Run(...);Task t2=Task.Run(...);...;Task.WaitAny(t1,t2);

TaskFactory类提供:Task.Factory.ContinueWhenAll(任务数组,前期任务)

ContinueWhenAll,ContinueWhenAny

并行计算中异常处理

try{

Task taskobject=;

taskobject.Start();

taskobject.Wait();

}

catch(AggregateException ae){

//将多层的嵌套异常“展平”为一层

ae.Flatten();

foreach(Exception ex in ae.InnerExceptions){

...

}

}

线程中断取消

public Volatile bool IsCancelRequested=false;

Public void ThreadFunction(){

if(IsCancelRequested){

return;

}

}

线程统一取消模型

CancellationToken的常用属性和方法

ThrowlfCancellationRequested() 方法 检测到取消请求时,抛出OperationCanceledException

IsCancellationRequested 只读 外界是否提出取消请求

CancellationTokenSource的常用属性和方法

Cancell() 方法 外界调用表明“想取消操作”

Token 只读属性 共外界使用CancellationToken对象

IsCancellationRequested 只读属性 外界调用Cancel()方法后,此属性未true

取消模型示例代码

private CancellationToken _token;

public ThreadTFuncObject(CancellationToken token){

_token=token;

_token.Register(()=>{

//在此操作取消执行代码

})

}

public void DoWork(){

if(!_token.IsCancellationRequested ){

...

}

//创建取消令牌对象,传值给线程函数

var tokenSource=new CancellationTokenSource();

var obj=new ThreadFuncObject(tokenSource.Token);

//启动“可以取消”的线程

Thread th=new Thread(obj.DoWork);

th.Start();

//发出“取消”命令

tokenSource.Cancel();

Task取消

var cst=new CancellationTokenSource();

//创建一个关联了取消令牌的Task对象

Task tsk=new Task(taskFunction,cts.Token);

抛出TaskCanceledException即可将Task状态置为canceled

private void btnTask_Click(object sender,EventArgs e){

console.WriteLine("****btnTask_Click******");

List taskList=new List();

TaskFactory taskFactory=new TaskFactory();

for(int i=0;i

taskList.Add(taskFactory.StartNew(()=>TestThread("Task")));

}

taskFactory.ContinueWhenAll(taskList.ToArray(),t=>Console.WriteLine("****ContinueWhenAll******"););//所有线程完成执行

taskFactory.ContinueWhenAny(taskList.ToArray(),t=>Console.WriteLine("****ContinueWhenAny******"););//某个线程完成就执行

Task.WaitAll(taskList.ToArray());

Console.WriteLine("****btnTask_Click******");

}

Entity Framework

static async void ShowProducts(){//获取表单数据

using(var context=new NorthwindEntities){//创建context对象,NorthwindEntities为数据库对象

context.Database.Log=Console.WriteLine();//记录日志

int count=0;

var query=from p in context.Products

select p;//用拓展方法 var query=context.Products.Where(p=>p.ProductName.Length>1);

foreach(var product in query){

Console.WriteLine(product.ProductName);

}

}

}

数据新增

using(var context=new NorthwindEntities){//创建context对象,NorthwindEntities为数据库对象

{

User user=new User(){

...}

context.User.add(user);

//方法二

context.Entry(user).State=System.Data.EntityState.Added//获取入口

修改删除的时候指定ID

user.ID=8;

context.Entry(user).State=System.Data.EntityState.Modified//修改

context.User.Attach(user);//附加到上下文;

context.Entry(user).Property(u=>u.LoginName).IsModified=true;//修改某个列

context.SaveChanges();//变化存到数据库

}

异步查询

static async void ShowProductsUseAsync(){//获取表单数据

using(var context=new NorthwindEntities){//创建context对象,NorthwindEntities为数据库对象

await context.Products.ForEachAsync((product)=>{

Console.WriteLine(product.ProductName);

})

}

}

static void UseView(){

using(var context=new NorthwindEntities){

foreach(var product in context.Current_Product_Lists){

Console.WriteLine(product.ProductName);

}

}

}

static void useStoreProcedures(){//调用存储过程

using(var context=new NorthwindEntities){

Console.WriteLine("input product id:);

int id=int.Parse(Console.ReadLine());

var product=context.GetProduct(id).FirstOrDefault();

if(product!=null){

Console.WriteLine(product.ProductName);

}

}

}

}

EF延迟加载技术

IQueryable temp=from u in context.UserInfo

where u.UName.Contain("o")

select u;

1、用到的时候去查询数据

var temp2=from u in context.UserInfo

where u.ID>0

select u;

foreach(var userInfo in temp2){

}

2、大数据查询优化,大表单独查询,数据组合查询

使用临时表降低死锁概率

select * into ##Tb from UserInfo

Eager Loading 预装载

public async TestFetchFirstPersonUseInclude(){

using(var context=new MyDBEntities)()){

Person person=await context.People.Include("IdentityCard").FirstOrDefaultAsync();

if(person!=null){

Console.WriteLine(person.Name,person.IdentityCard);

}

}

}

协变 把一个子类的泛型集合赋值给父类的泛型集合。外部用的时候是父类泛型

List ListInt=new List(){1,2,3};

Listlistobj=ListInt;

逆变

CodeFirst适合改造原来用实体类的项目

UserInfo.cs页面

public class UserInfo(){

public UserInfo(){

OrderInfo=new HashSet();

}

[Key]

public int Id{get;set;}

public int SName{get;set;}

public int Age{get;set;}

public virtual ICollection OrderInfo{get;set;}

}

Program.cs页面//相关引用可通过新增空的EF数据实体,更改webconfig数据库配置

class Program{

static void Main(string[] args){

CodeFirstDbContext dbContext=new CodeFirstDbContext();//改为单例模式保证只能生成一个上下文对象

dbContext.Database.CreateIfNotExists();//若无数据库则新增

UserInfo userInfo=new UserInfo();

userInfo.SName="xyz";

userInfo.Age=10;

dbContext.UserInfo.Add(userInfo);

dbContext.SaveChanges();

}

}

CodeFirstDbContext.cs 上下文对象页面

public class CodeFirstDbContext:DbContext{

public CodeFirstDbContext():base("name=DataModelContainer"){//此为webconfig数据库链接对象

}

public DbSet UserInfo{set;get;};

}

8、设计模式

1、单例模式(类在整个进程中被实例化一次)(简化构造函数消耗,例链接池创建)

1)private static object Singleton_Lock=new object ();

private static Singleton _Singleton=null; //静态参数保证唯一

private long Result=0;

private Singleton(){//构造函数

for(int i=0;i

Result+=i;

}

Console.writeLine(Result);

}

public static Singleton CreateInstance(){

if(_Singleton==null){//是否初始化过

Lock(Singleton_Lock){//一开始线程都在这等待

if(_Singleton==null){//检查是否为空

_Singleton=new Singleton();

}}

return _Singleton;

}

2)public class Singleton { // 定义一个静态变量来保存类的实例 private static Singleton uniqueInstance; // 定义私有构造函数,使外界不能创建该类实例 private Singleton() { } public static Singleton GetInstance() { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } }

对象销毁显示回收继承IDisposable接口

析构函数用于清理非托管资源

2、简单工厂

上端

class program

{

static void Main(string[]args){

//Human human=new Human();

//IRace human=new Human();

IRace human=Factory.CreateInstance(Race.Human);

}

}

public class Factory{

Public static IRace CreateInstance(RaceType raceType ){

switch(raceType ){

case RaceType.Human:

return new Human();

}

}

Public enum RaceType{

Human

}

}

Public interface IRace{

void ShowKing();

}

Public class Human:IRace{

public void ShowKing(){

Console.WriteLine("The King");

}

}

配置项优化

private static string RaceTypeConfig=ConfigurationManager.AppSettings["RaceTypeConfig"];

Public static IRace CreateInstance(RaceType raceType ){

switch((RaceType)Enum.Parse(typeof(RaceType),RaceTypeConfig) ){

case RaceType.Human:

return new Human();

}

反射优化

private static string RaceTypeReflect=ConfigurationManager.AppSettings["RaceTypeReflect"];

Public static IRace CreateInstance(RaceType raceType ){

string assemblyName=RaceTypeReflect.split(',')[0];

string TypeName=RaceTypeReflect.split(',')[1];

return (IRace)(Activator.CreateInstance(assemblyName,TypeName).Unwrap())

}

3、工厂方法

//解决工厂方法内部的高度耦合,拆分为多个类 (对拓展开放,对修改封闭)

IFactoryMethod humanFactory=new HumanFactory();

IRace human=HumanFactory.CreateInstance();

4、抽象工厂

//拆分为多个方法 工厂职责稳定才使用

使用HttpClient组件发出Get请求

static HttpClient getHttpClient(){

var client=new HttpClient();

client.BaseAddress=new Uri("http://localhost:12623");

client.DefaultRequestHeaders.Add("Accept","application/json");

return client

}

static async Task TestGetFromWebServer(){

Console.WriteLine("向web Server发出HTTP GET请求:\n");

var client=getHttpClient();

Console.WriteLine("收到服务器发回的数据");

client.DefaultRequestHeaders.Add("my-header","my-header value");//自定义head添加

string result=await client.GetStringAsync("api/myservice");

string searchWhat="中国人 abc";

string searchUrl=$"api/myservice/search?value={searchWhat}";

string result1=await client.GetStringAsync(searchUrl);//包含查询字符串的请求

Console.WriteLine(result);

}

响应HTTP请求

[HttpGet]

[Route("headers")]//可通过Request.Headers获取Headers

public IActionResult Get()}{

Response.StatusCode=200;

return Json(new MyClass(){

Info="Web Server发回的Json格式信息";

Id=100

})

}

包含查询字符串的响应

[HttpGet]

[Route("[action]")]

public IActionResult Search(string value)}{

Response.StatusCode=200;

return Json(new {

message="正在搜索:"+value;

})

}

向客户端Post数据

var response=await client.PostAsJsonAsync("api/myService",data);

response.EnsureSuccessStatusCode();

var result=await response.Content.ReadAsStringAsync();

Console.WriteLine(result);

服务端接收Post数据

[HttpPost]

public IactionResult Post([FromBody]MyClass obj){//[FromBody]指明冲Http请求的Body提取数据并实例化-*/

return ok(obj)

}

MongoDB(NoSQL)

DatabaseDatabase

CollectionTable

DocumentRow

{Key:value}Column

db.foo.save({id:1,value:"Hello,World"});//数据插入覆盖

db.foo.insert({id:1,value:"Hello,World"}); //插入

db.foo.insert({id:2,value:1}); //插入

db.foo.update((_id:2).($inc:(value:1)))//$inc相当于+=

db.foo.update((_id:2).($set:(x:1)))//set新增属性,unset移除属性

show collections

db.foo.find({_id:($lt:10)},{_id:1,value:1}).sort({id:-1});//查询语句,$lt小于显示id小于10的数据,sort排序

db.foo.remove({})//删除数据

db.foo.drop();//删除collections

ASP.Net Core MVC

使用Html辅助方法和TagHelper生成网页链接

@Html.ActionLink("Homepage","Index","Home",new{One=1,Two=2},new {@class="btn btn-defualt"});//要显示的文本,Action,Controller,传参数,样式

@Html.ActionLink("在本Controller内跳转","hashcode");

@Html.ActionLink("生成查询字符串","para","new{Name="张三"}");

@Html.ActionLink("跳转到另一个控制器的Action","index","mySimplest");

TagHelper生成跳转到另一个控制器Action链接

使用条件,project.json中添加“Microsoft.AspNetCore.Mvc.TagHelpers”

视图中添加@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers

处理管线

public void Configure(...){

app.use(async(context)=>{//lambda表达式定义的中间件

context.Response.ContentType="text/html;charset=utf-8";

context.Item["info"]=$"1";//中间件间传值

await context.Response.WriteAsync($"

Ready

");

await next();//调用下一个中间件

});

app.Run(async(content)=>{

await context.Response.WriteAsync($"

{context.item["info"]}

");

})

}

通过Map实现分支管线

public ConfigureMapping(... app){//修改环境变量为Mapping

app.Map("/branch",ConstrunctBranchPipeline)

app.Run(asyn context=>{

await context.Response.WriteAsync($"

Ready

");

})

}

通过MapWhen实现分支管线

public ConfigureMapWhen(... app){

app.MapWhen(context=>{

return context.Response.Query.ContainsKey("branch");

}

,ConstrunctBranchPipeline)

app.Run(asyn context=>{

await context.Response.WriteAsync($"

Ready

");

})

}

依赖注入与loC容器

ASP.NET core中能被loC容器创建的对象称为服务对象(Service)

Startup类中ConfigureService()方法完成对象的注册工作

pulic interface IDateTime{//接口

DateTime Now{get;}

}

pulic class SystemDateTime:IDatetTime{//实现接口的类

public DateTime Now{

get{return DateTime.Now;}

}

}

public void ConfigureServices(IServiceCollection services){

services.AddMvc();

services.AddTransient();

}

构造方法注入设计控制器

public class HomeController:Controller{

Private readonly IDateTime _dateTime;

public HomeController(IDateTime dateTime){

_dateTime=dateTime;

}

}

[FromService]方法注入

public IActionResult About([FromService]IDateTime dateTime){

ViewData["Message"]="当前时间:"+dateTime.Now

return View();

}

视图注入

@inject DenpendecyInejctofController.IdateTime dateTimeObj

当前时间:@dateTimeObj.Now

依赖注入对象的生命周期

Transient:每次刷新,总得到两个全新的对象

Scope:每次刷新,只得到一个对象,但与上次刷新的对象不同

Singleton:每次刷新,只访问相同的对象,由loC容器创建

让ASP.NET core项目支持静态文件访问

1、在project.json中添加项目依赖 "Microsoft.AspNetCore.StaticFiles"

2、向处理管线中添加中间件

public void Configure(...){

...

app.UseStaticFiles();

...

}

路由系统

1、依据Http请求的URL确定应该创建哪个Controller的实例,并调用哪个Action

2、提供一些辅助方法用于生产Web页面中用户可点击的链接

1、在Startup类的Configure()方法中定义的“全局性”的路由

public Configure(... app){

app.UseDeveloperExceptionPage();

app.UseStaticFiles();//支持静态文件访问

app.UseMvc(routes=>{

routes.MapRoute("Default","{controller=Home}/{action=Index}/{id?}");//等于号赋默认值,?表示可有可无

});

app.Run(asyn context=>{

await context.Response.WriteAsync($"

Ready

");

})

}

2、以Attribute形式定义的“局部性”路由

[Route("api/[controller]")]

public class MyServiceController:Controller{

[HttpGet("[Action]/{value:int:min(100)}/{argu}")]//value为参数名

public string GetValue(int value,int argu){

return $"value={value}";

}

}

对应的URL:http://网站名称/api/myservice/GetValue/105 //控制器实例/方法名/参数

Action参数绑定

public class MyPoint{

public double x{get;set;}

public double y{get;set;}

}

[HttpGet("point")]

public IActionResult GetPoint(MyPoint point){

return ok(point);

}

示例:http://localhost:9303/api/argument/point?x=100&y=200

Action的返回值

1、返回void的Action

[HttpGet("void")]

public void testReturnVoid(){

}

2、返回IActionResult的Action

[HttpGet("json")]

public void IActionResult GetJson(){

Response.StatusCode=200;//设置状态码为200

return Json({name="xyz",age=40});//若状态码为200,则可用Ok()方法生成Json字符串

}

3、返回集合对象的Action

[HttpGet("mydata")]

public IEnumerable testotherReturnType(){

return MyData.CreateMyDataobjects();//默认情况下,ASP.NET core会将集合对象序列化为Json数组

}

4、返回HTML的Action

[HttpGet("html")]

public IActionResult testHtml(){

Response.ContentType="text/html";

return Content("

Hello

");

}

编写异步Action

耗时较长,访问网络和磁盘,I/O密集操作的

设计视图,Razor引擎

ViewData、ViewBag、ViewModel(Action to View)

ViewData:

public IActionResult useViewData(){

ViewData["CompanyName"]="百度";

}

@ViewData["CompanyName"]

ViewBag:

public IActionResult useViewData(){

ViewBag.CompanyName="百度";

}

@ViewBag.CompanyName

ViewModel:

public class informatonViewModel(){

[Display(Name="一个Int值")]

public int IntValue{get;set;}

public string StringValue{get;set;}

public DateTime datetime{get;set;}

}

public IActionResult useViewData(){

var info=new informatonViewModel(){

IntValue=1,

StringValue="Hello",

datetime=DateTime.Now

};

return View(info);

}

@model informatonExchange.informatonViewModel

@Model.IntValue

模型绑定机制(Action接收外部传入的数据)

@Html.ActionLink("Homepage","Index","Home",new{One=1,Two=2},new {@class="btn btn-defualt"});//要显示的文本,Action,Controller,传参数,样式

Post方式提交信息(定义两个Action,一个响应Get,一个响应Post)

[HttpGet]

public IActionResult GetAndPost(){

var vm=new MyViewModel(){//设置初始值

Value=1,

Information="初始化对象",

};

return View(vm);

}

public IActionResult GetAndPost(MyViewModel model){

return View("GetAndPostResult",model);//传到视图GetAndPostResult

}

TempData与Session

TempData(重定向后数据不丢失)

跳转时将数据保存到Session,进入控制器从Session移除

TempData["user"]="xyz"

启用Session的条件

project.js中添加"Microsoft.AsoNETCore.Session"

在Startup.cs中配置Session

public void ConfigureServices(){

service.AddMvc();

service.AddSession();

}

public void Configure(){

app.UseSession();

app.UseMvcWithDefualtRoute();

}

Action中通过HttpContext.Session.GetInt32("value")获取数据,HttpContext.Session.SetInt32("value",0)保存数据

服务端数据验证

Controller中的数据验证

public class ExpressionInfo(){

[Required(ErrorMessage="必须输入一个操作数")]

[Display(Name="第一个操作数")]

public int Operand1{get;set;}

[Required(ErrorMessage="必须输入一个操作数")]

[Display(Name="第二个操作数")]

public int Operand2{get;set;}

[Required(ErrorMessage="必须选择一个操作类型")]

[Display(Name="选择操作类型")]

public string MathOperator{get;set;}

}

public ActionResult Calculate(){

Listoperators=new List{"加","减","乘","除"};

ViewBag.operators=new SelectList(operators,"加");

return View();

}

@using(Html.BeginForm()){//生成Html的

元素

@Html.ValidationSummary(true)//生成一个

,汇总那些与单个属性值无关的数据验证信息

输入表达式信息

@Html.LabelFor(model=>model.Operand1)

@Html.EditorFor(model=>model.Operand1)

@Html.ValidationMessageFor(model=>model.Operand1)

@Html.DropDownList("MathOperator",

(IEnumerable)ViewBag.operators)

}

[HttpPost]

public IActionResult Calculate(ExpressionInfo express){

if(ModelState.IsValid){//数据验证

ViewBag.result=expr+result;

return View("CalculateResult");

}

return View();

}

MVC实现CRUD

使用Bower安装前端框架

MVC(直接访问类下面的某个方法)

M:Model模型,存储并处理用户请求的数据

V:View视图,显示数据接受用户请求

C:Controller控制器,获取用户的请求,处理请求

如何请求?在B/S结构用户请求Server的唯一途径就是URL

请求什么?请求一个服务,对于程序来讲就是请求一个或多个功能。对于C#来讲就是请求类中的一个方法

类名和方法在url上怎么体现? http://localhost:8080/类名(Controller)/方法名(Action)

不是所有的类都能访问(控制器)

1、类名必须以Controller结尾 2、必须继承Controller抽象类 3、类必须是Public的

不是所有方法都能访问(Action)

1、方法必须是Public的 2、方法不能加持性([NonAction]) 3、方法不能重载 4、重载的方法需要通过特性来区分([HttpGet],[HttpPost],[NoAction],[ActionName("reg")]等等)

控制器默认代码分析

控制新建的默认代码

View()方法是什么?怎么用?

View方法是从Controller类继承下来的方法,有8个重载

1、View():返回与Action名相投的视图文件(文件搜索路径,/Views/Account/UserList.aspx,/Views/Account/UserList.ascx,/Views/Shared/UserList.aspx,/Views/Shared/UserList.ascx,/Views/Account/UserList.cshtml,/Views/Account/UserList.vbhtml,/Views/Shared/UserList.cshtml,/Views/Shared/UserList.vbhtml),假设控制器为Accont,Action为UserListView()等价于View("UserList")文件名搜索顺序如右侧

2、View(String)呈现指定的视图文件

3、View(Object)文件查找同上,将Model传递到页面

4、View(IView)呈现自定义视图

5、View(String,Object)在指定页面传递Model对象

6、View(String,String)在视图页面室友母版页,第二个参数为母版页路径

7、View(Iview,Object)在自定义视图中传递Model对象

8、View(String,String,Object)是在使用母版页的视图中传Model对象

ActionResult是什么

1、System.Web.Mvc.ContentResult:返回一串字符串

例:return Content("ASP.NET MVC")

2、System.Web.Mvc.EmptyResult:返回空内容

例:return new EmptyResult()

3、System.Web.Mvc.FileResult 返回一个文件,应用做验证码

1)return new FileContentResult(new byte[1024],"image/jpeg")

例:Image img=Image.FromFile(Server.MapPath("~/Image/logo.gif"));

MemoryStream ms=new MemoryStream();

img.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);

byte[] data=ms.GetBuffer();

return new FileContentResult(data,"image/jpeg")

2)return new FilePathResult("logo.jpg","image/jpeg");

3)return new FileStreamResult(new FileStream("logo.jpg",FileMode.Open),"image/jpeg")

例:FileStream fs=new FileStream(Server.MapPath("~/Image/logo.gif"),FileMode.Open)

return new FileStreamResult(fs,"image/jpeg")

4、System.Web.Mvc.HttpUnauthorizedResult:未经授权的请求结果

例:return new HttpUnauthorizedResult();

5、System.Web.Mvc.JavaScriptResult:返回JS脚本

例:return JavaScript("");

6、Ststem.Web.Mvc.JsonResult:返回Json格式,常用于Ajax的应用

例:return Json(new {Name="jack",Age=20},JsonRequestBehavior.AllowGet)

7、System.Web.Mvc.RedirectResult:重定向站内或站外

例:return Redirect("url");

8、System.Web.Mvc.RedirectToRouteResult:站内请求

例:return RedirectToAction("Login");//根据控制器和Action

return RedirectToRoute("Default");根据路由名称

9、System.Web.Mvc.PartialViewResult:部分视图

例:return PartialView("~/Views/UserControl/UserLogin.ascx")

ULR匹配模式

ULR是如何匹配的?

根据键入的URL在路由列表搜索,如果没有匹配的项则返回404错误

路由信息在哪里添加?

在APP_Start目录下的RouteConfig.cs文件添加

routes.MapRoute()方法有什么用?怎么用?

routes.MapRoute(

name:"Default";//必须唯一,可以为null

url:"{controller}/{action}/{id}";

defaults:new {controller="Home",action="index",id=UrlParameter.Optional,age=20}

constraints:new {age=@"[1-9]|\d{2}"};

namespaces:new string[]{"BookShopMVC.Controllers"}

)

1、占位符controller和action必须有

2、url中要特别注意空格

3、分隔符:/表示路径的分隔符,分隔Url不同的信息

4、特殊的匹配符:*匹配剩余的部分

例:URL:“{controller}/{action}/{*name}”

url为:Account/Register/a/b/c 则name=a/b/c

贪婪匹配:优先匹配完前面的占位符所有可能性,再匹配后面的占位符

defaults默认值:

例1:url:"{controller}/{action}/{*name}-{age}",

defaults:new {controller="Home",action="index",name="jack",age=20} 默认值无效

例2:url:"{controller}/{action}/{*name}-{age}/{addr}",

defaults:new {controller="Home",action="index",name="jack",age=20,addr="wuhan"} 仅addr为默认值

客户端数据获取

1、表单数据

Request.Form["name"]

2、URL上的数据

Request.QueryString["name"]

3、路由数据

object obj=RouteData.Values["name"]

4、方法上的参数

public ActionResult Register(string name),可映射为表单元素,URL参数,路由数据,如果有name有冲突,优先级顺序为:表单元素>路由数据>URL参数

控制器数据如何传递到视图

ViewBag和ViewData(两者处理的是一个数据源,作用于ViewResult指向的视图)

ViewBag是dynamic类型

ViewBag.data="ASP";

@ViewBag.data

ViewData是Object类型

ViewData["data"]="JSP"

例:return Redirect("/Home/Login")//重定向ViewData丢失

return RedirectToAction("Login")//转发到另一个Action

TempData(重定向后数据不丢失)

跳转时将数据保存到Session,进入控制器从Session移除

TempData["user"]="xyz"

强类型视图

1、控制器参数为Model类型

通过泛型类ViewPage指定Model类型

ViewData.Model=类;

1)Model为一个对象

1、只显示不能给Model赋值,StudentName为属性名2、 适用于表单元素,能够赋值给Model,StudentName为属性名,不区分大小写3、 适用于表单元素,能够赋值给Model,stu为Action参数名,StudentName为属性名,不区分大小写

4、建议前缀统一,要么统一带前缀,要么都不带

2)Model为一个集合

1、通过索引获取对象,以下案例使用索引0获取集合的第一个对象

2、已get方式第一次请求时Model为null,所以要非空判断

3、直接使用索引或通过方法参数名带索引,两种方式建议统一使用第一种,因为不能互相访问各自设置的数据

4、建议:属性前缀要统一,要么都带前缀,要么都不带

数据绑定(了解)

1、Bind设置Model绑定的方式

Exclude:不进行模型映射的操作

Include:进行模型映射的操作

Prefix:Model使用的前缀

表单数据验证

Model类型数据上编写

Inherits="System.Web.Mvc.ViewPage"

1、引入组件System.ComponentModel.DataAnnotations

2、引入命名空间using System.ComponentModel.DataAnnotations;

3、在属性上,使用特性编写验证规则

1)Required(必填信息)

[Require(ErrorMessage="请输入学生姓名")]

2)Compare(比较验证,与其他的属性进行比较)

[Compare("PassWord2")]

3)StringLength:字符串的长度验证

[StringLength(5)]

4)Range(数字,整数,浮点,时间等数据范围)

[Range(10,20)]

5)RegularExpression(正在表达式验证)

[RegularExpression(@"\d{2}")]

6)EmailAddress(Email格式)

4、在UI上使用验证规则

1)使用强类型视图模型

Inherits="System.Web.Mvc.ViewPage"

2)引用样式Content/Site.css

3)在要验证的控件后面添加显示指定属性的错误信息

4)建议:使用

样式更丰富,表单数据不丢失

5、控制器对Model的处理

1、Action方法上参数传入Model数据

Public ActionResult Register(Student stu)

2、业务操作前判断Model数据是有效

if(ModelState.IsValid)

1)ModelState是模型状态信息

2)可以使用ModelState添加业务逻辑错误信息

ModelState.AddModelError("errPwd","密码错误")

3)在客户端使用显示错误信息

3、返回Model

return View("~/Views/Home/Index.aspx",stu)

你可能感兴趣的:(C#,c#,服务器)