c# Mvc常用特性


 介绍一些在开发中非常有用的MVC特性,如下:

BindAttribute
Remote
HandleError
HiddenInput

1.BindAttribute
使用BindAttribute的目的是限制用户在提交form表单时使用合适且正确的值。当我们提交一个表单时,就会检查每一个实体上绑定的特性。

假设我们已经有下面一个Employee实体类:

public class Employee
{
    public string Name { getset; }
    public string Email { getset; }
    public string Address { getset; }
    public string PhoneNo { getset; }
}

现在如果我们只想提交Email,Name和PhoneNo,而我们不想提交地址,这时我们可以在实体类上添加如下特性:
[Bind(Exclude="Address")]
   public class Employee
   {
       public string Name { getset; }
       public string Email { getset; }
       public string Address { getset; }
       public string PhoneNo { getset; }
   }

BindAttribute要在System.Web.Mvc命名空间下使用,使用BindAttribute,我们可以在提交表单时对字段进行一些控制。在下面的图中,我们已经在提交的form数据中得不到Address的值了。

我们也可以将BindAttribute直接用在Action的参数中,像下面这样:

public Actionresult emprigister([Bind(Exclude="Address")],Emploree emp)
{
}

2.RemoteAttribute
假设我们有一个注册表单,里面有邮箱文本框,当输入邮箱后,我们想检查输入的邮箱是否在数据库中已经存在,如果存在,则不提交表单,这时我们可以使用RemoteAttribute,通过RemoteAttribute,我们可以在不用提交表单就可以先进行一些服务端验证。

我们可以在下面的例子中使用RemoteAttribute:

public class Employee
{
    public string Name { getset; }
    [Remote("CheckEmail","Employee",ErrorMessage="Email is already exist")]
    public string Email { getset; }
    public string Address { getset; }
    public string PhoneNo { getset; }
}

RemoteAttribute的第一个参数是一个Action名字,第二个是Controller名字,第三个是如果邮箱已存在后显示给用户看的提示信息。当我们输入完邮箱后,CheckEmail方法将被执行并检查邮箱是否存在。
public JsonResult CheckEmail(string Email)
  {
      //Check here in database if it exist in database return true else false.
      return Json(false, JsonRequestBehavior.AllowGet);
  }


3.HandleError Attribute
我们已经有很多方法在MVC中处理异常,比如用try catch,或者使用Filter,或者通过第三方库比如elmah。但是MVC也提供了一个HandleErrorAttribute去处理异常,如下:

[HandleError()]
public ActionResult CheckError()
  {
     int a = 10;
     int b = 0;
     int k = a / b;
     return View();
  }

在web.config文件中,我们添加如下两行:

<customErrors mode ="On" defaultRedirect ="Error.cshtml">
</customErrors>

在shared文件夹下创建一个视图Error.cshtml,然后运行程序,如果运行上面的CheckError()方法,你刚创建的Error.cshtml将会显示出来。

我们也可以使用HandleErrorAttribute给不同类型的异常显示不同的视图页面。

[HandleError(ExceptionType=typeof(DivideByZeroException),View="DivideByZeroErrorView")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "NullRefrenceErrorView")]
public ActionResult CheckError()
       {
           int a = 10;
           int b = 0;
           int k = a / b;
           return View();
       }

4.HiddenInput Attribute
如果我们想对用户隐藏一些实体字段,我们可以使用HiddenInput特性。

public class Employee
    {
        [HiddenInput(DisplayValue=false)]
        public string Name { getset; }
        [Remote("CheckEmail","Employee",ErrorMessage="Email is already exist")]
        public string Email { getset; }
        public string Address { getset; }
        public string PhoneNo { getset; }
    }

在以上的实体中,我用HiddenInput特性去描述Name字段。这样程序运行后在浏览器中Name字段将不在显示。因此HiddenInput给我们d 在实体字段上多了一些额外的控制。

posted @ 2020-07-27 13:38 青蛙學堂 阅读(13) | 评论 (0)编辑 收藏

boootstrap talbe多列checkbox设置


boootstrap talbe多列checkbox设置

boootstrap talbe 列值进行格式化操作:

 {
                          title: '审核',
                          field: '审核',
                        //  width: '10%',
                         // align: "left",
                          formatter: function (value, item, index,row) {
                              if (value == '1') {
                                  return '<input type="checkbox"   id="a_' + index + '" checked = "checked"/>';
                              }
                              else if (value == '0') {
                                  return '<input type="checkbox"  id="a_' + index + '" />';
                              }
                              else if (value == null) {
                                  return '<input type="checkbox"  id="a_' + index + '" />';
                              }
                          }
                      }

//***************************************************8

2. 在table的cell单击事件里取值赋值

 onClickCell:function(field, value, row, $element,index)
            {
               // alert("单击cell-" + value);
               // alert("单击cell-" + row.id);
               // if ($('#a_' + index).get(0).checked) {
                if ($('#a_' + index).is(':checked')) {
                    row.审核 = "1";
                } else {
                    row.审核 = "0";
                }

                alert(value+"单击cell-" + row.id);


            },

posted @ 2020-07-24 10:31 青蛙學堂 阅读(13) | 评论 (0)编辑 收藏

c# 抽象类和接口

抽象类与接口紧密相关。然接口又比抽象类更抽象,这主要体现在它们的差别上:1)类可以实现无限个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承问题的。2)抽象类当中可以存在非抽象的方法,可接口不能且它里面的方法只是一个声明必须用public来修饰没有具体实现的方法。3)抽象类中的成员变量可以被不同的修饰符来修饰,可接口中的成员变量默认的都是静态常量(static final)。4)这一点也是最重要的一点本质的一点"抽象类是对象的抽象,然接口是一种行为规范"。
  以上是它们本身的异同,下面再来从实际应用讲讲它们的异同!
  不同之处:
  1、定义 
  抽象类表示该类中可能已经有一些方法的具体定义,但是接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。
  1、用法 
  1)在继承抽象类时,必须覆盖该类中的每一个抽象方法,而每个已实现的方法必须和抽象类中指定的方法一样,接收相同数目和类型的参数,具有同样的返回值,这一点与接口相同。
  2)当父类已有实际功能的方法时,该方法在子类中可以不必实现,直接引用的方法,子类也可以重写该父类的方法(继承的概念)。
  3)而实现 (implement)一个接口(interface)的时候,是一定要实现接口中所定义的所有方法,而不可遗漏任何一个。
  4)另外,抽象类不能产生对象的,但可以由它的实现类来声明对象。
  有鉴于此,在实现接口时,我们也常写一个抽象类,来实现接口中的某些子类所需的通用方法 



对于C#初学者来说,abstract抽象类在网上的定义和解释说了一大堆,却往往我们忽视了为何要使用abstract类,使用它的意义在哪里。面试的时候也会有人问起使用它有什么好处,因为不适用它用自己定义的类也可以实现。那么为什么要使用抽象类?

那么我们什么时候应该用抽象类呢?
如果一个类设计的目点是用来被其它类继承的,它代表一类对象的所具有的公共属性或方法,那个这个类就应该设置为抽象类。

抽象类与其它的类有什么区别呢?
抽象类是不能够被实例化的。如果一个类中包含有抽象方法,那么这个类一定要声明为抽象类。同时,抽象方法一定需要在子类中重写,让抽象方法成为一个具体的实实在在的方法。

相信大家在网上一定看过很多这类解释了吧?好吧,不理解的我们一起来看看通俗易理解的说法吧:

比如说:我们需要创建 “狗”、“猫”、“鱼”、“马”这些对象(类),我们可以说他们有一些共同的属性像嘴巴、尾巴、重量、颜色、大小等等一些共同的属性(properties),但是它们彼此的属性的形状是不同的(如嘴巴),在这种情况下,我们如果一个个去定义各自类似的属性是不是比较繁琐?如果用抽象类是不是很方便的给他们去继承。抽象类也有个更加好的地方,体现在“同质异像”就是实质相同实现形式不同的方法继承上,例如上面的狗、猫、马等的呼吸这个方法或者跑的速度的方法形式不同,我们这个是用定义一个抽象方法,让他们各自的类去实现它是不是很方便。“抽象”的意义正在于此。将共同的东西抽出来封装,但不实现只给继承。

posted @ 2020-07-24 08:51 青蛙學堂 阅读(8) | 评论 (0)编辑 收藏

c# 使用接口

c#为什么要使用接口?通俗的讲,就是为了降低耦合度。给大家看一个我见过的很搞笑的例子。看看下面的程序:一个学校里边,有两种人:学生、老师。他们都要吃饭和睡觉。
------------------------------
public interface I人
{
    void 吃饭();
    void 睡觉();
}
public class 学生:I人
{
    public void 吃饭()
        { //去食堂吃饭 }
    public void 睡觉()
        { //回寝室睡觉 }
    //其他特有方法,比如泡妞、打游戏
}
public class 老师:I人
{
    public void 吃饭()
        { //回家吃饭 }
    public void 睡觉()
        { //回家睡觉 }
    //其它特有方法,比如为生儿育女传宗接代的历史使命努力等“不足为外人道也”的事情
}
public class 学校
{
    public void 开饭(I人 ren)
        { ren.吃饭(); }
    public void 放学(I人 ren)
        { ren.睡觉(); }
}
-----------------------------
    这里就用到了里氏代换原则,"开饭()"和"放学()"的参数都是人,那么这个地方如果换成学生和老师肯定也可以。
I人 某学生 = new 学生();
某学生.开饭();
某学生.放学();
这样执行的结果就是学生回寝室吃饭。
I人 某老师 = new 老师();
某老师.开饭();
某老师.放学();
这样执行的结果就是老师回家吃饭。
    为什么要这样写呢?这样写有什么好处呢? 我在开饭的时候完全可以直接调用“学生.吃饭();”、“老师.吃饭();”。接着看,有一天,学校里来了第三种人,家长。 家长既不是去寝室睡觉也不是回家睡觉,而是旅馆睡觉,既不是去食堂吃饭也不是回家吃饭,而是去下馆子。 这个时候学校这个系统该怎么处理呢? 如果原来没有定义"I人"这个接口那就麻烦啦,所有用到人的地方代码都要改。 现在不一样了,我可以直接定义一个类:家长,这个类实现人这个接口就可以了。 好,看代码:
------------------------------
public class 家长:I人
{
    public void 吃饭()
        { //下馆子 }
    public void 睡觉()
        { //去旅馆睡觉 }
    //其它特有方法,比如会见老师,晓之以钱,动之以利等等,不一而足
}
-------------------------------
    在调用的时候不需要修改任何代码,还和原来一样:
I人 某家长=new 家长();
某家长.开饭();
某家长.放学();
    轻松搞定家长的食宿问题! 这样一来学校来再多的客人都没关系啊,绝对可以应付自如,这也就是传说中的可扩展性!不知道大家看到这里是不是能够明白接口的作用。如果你还不明白,那么你把人这个接口去掉,自己写一个学校开饭和放学的类,然后再加一个家长这个新新人类进去,看看你的代码是什么样子的,再想一下在人口这么多的中国,万一哪天你的学校里来了成千上万个新新人类你该怎么办!
    先声明一下,这个案例可不是我想出来的~~但是很经典,是不?
    然后我们就很好理解了,为什么用别人的东西要实现接口呢?很直接的一个原因是这样一来,编程的复杂度就可能会大大降低了,不是么?

posted @ 2020-07-24 08:49 青蛙學堂 阅读(157) | 评论 (0)编辑 收藏

css计算宽度高度vh-vw

calc 是 css3提供的一个在css文件中计算值的函数:
     用于动态计算长度值。
     需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);
     任何长度值都可以使用calc()函数进行计算;
     calc()函数支持 "+", "-", "*", "/" 运算;
     calc()函数使用标准的数学运算优先级规则;
calc(100vh - 10px)  表示整个浏览器窗口高度减去10px的大小 calc(100vw - 10px)   表示整个浏览器窗口宽度减去10px的大小 一般用来设置流式布局宽高,当然,你可以使用calc()给元素的border、margin、pading、font-size和width等属性设置动态值 calc()的兼容性如下,使用时需注意
 
在讲calc之前先说一下 vh  vw:
    vw  相对于视口的宽度。视口被均分为100单位的vw
   vh  相对于视口的高度。视口被均分为100单位的vh
   vmax 相对于视口的宽度或高度中较大的那个。其中最大的那个被均分为100单位的vmax
   vmin 相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vmin

posted @ 2020-07-23 14:12 青蛙學堂 阅读(12) | 评论 (0)编辑 收藏

easyui多列checkbox-未测试

 $('#grid').datagrid({
              columns:[[
                  {field:'CODE_NM',title:'名称',align:'center',width:'40%'},
                  {field:'a',title:'选项A',width:'15%',align:'center',
                      formatter: function (value, rowData, rowIndex) {
                                  if(value=="1"){
                                      return '<input type="checkbox"  id="a_'+rowIndex+'" />';
                                  }else if(value="0"){
                                      return '<input type="checkbox"   id="a_'+rowIndex+'" checked = "checked"/>';
                                  }
                                
                            }},
                  {field:'b',title:'选项B',width:'15%',align:'center',
                      formatter: function (value, rowData, rowIndex) {
                                  if(value=="1"){
                                       return '<input type="checkbox"  id="b_'+rowIndex+'" />';
                                  }else if(value=="0"){
                                       return '<input type="checkbox"  id="b_'+rowIndex+'" checked="checked"/>';
                                  }
                               
                            }}
              ]],
              width:'100%',
              hight:'100%',
              rownumbers:true,
              title:'列表信息',
              url:"getDetail",
              onClickRow:function(index,row){
                  $('#grid').datagrid('clearSelections');
                  if($('#a_'+index).get(0).checked){
                      row.a = "0";
                  }else{
                      row.a = "1";
                  }
                  if($('#b_'+index).get(0).checked){
                      row.b = "0";
                  }else{
                      row.b = "1";
                  }                  
              },
              dataType:"json",
              type:'post',
              onLoadSuccess:function(data){
              }
          
          }); 

 

posted @ 2020-07-23 09:59 青蛙學堂 阅读(16) | 评论 (0)编辑 收藏

事件和委托的区别

前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类…你是否也曾经被问到过?你又是否都答出来了呢?

关于面试中涉及到的事件的问题,我们只需要抓住几个关键点就好了:

(1)事件是委托的封装,可以理解为一种特殊的委托。

(2)事件里面其实就两个方法(即add_event()和remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进行的合并和移除,当调用事件的+=时其实是调用的事件里面的add_event()方法,同样-=调用的是remove_event()方法。

(3)事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。也有人说事件是对委托的阉割,大概也是这个意思。

如果回答的时候抓住了以上的3点,那么我想你的面试应该不会太差。毕竟面试那么短的时间,有一两个亮点就很不错了,你说呢。哪怕你对事件机制完全不懂,为了面试记住其中两点也是很好的,工作经验咱们没有,换工作的经验可不能没有哦~~扯远了,关于面试就到此为止。如果你还想继续将事件了解透彻,别着急,慢慢往下看。

1、事件的定义及由来:

定义事件:

public delegate void MyStudyEvent(object sender, EventArgs e);
public class TestEvent
{
   public event MyStudyEvent eMyStudyEvent;
}
 

将这段代码生成dll后,通过反编译工具reflector我们可以看到:

c# 基础事件

正如上文所说,可以看到当定义一个事件public event MyStudyEvent eMyStudyEvent的时候,编译器会自动给他生成两个方法add和remove,以及一个private的委托变量eMyStudyEvent。我们将反编译代码copy出来看看。

可以看到这两个方法的主要作用就是在向private变量eMyStudyEvent里面添加委托和移除委托。当调用事件的+=和-=时,eMyStudyEvent里面就合并和移除传过来的委托,当事件触发的时候,eMyStudyEvent变量就执行。这样设计也正好符合封装的原则,保证了内部变量的安全性。

//私有委托变量
private MyStudyEvent eMyStudyEvent;
//add方法合并委托到eMyStudyEvent里面
public void add_eMyStudyEvent(MyStudyEvent value)
{
    MyStudyEvent event3;
    MyStudyEvent eMyStudyEvent = this.eMyStudyEvent;
    do
    {
       event3 = eMyStudyEvent;
       MyStudyEvent event4 = (MyStudyEvent)System.Delegate.Combine(event3, value);
       eMyStudyEvent = Interlocked.CompareExchange<MyStudyEvent>(ref this.eMyStudyEvent, event4, event3)
    }
    while (eMyStudyEvent != event3);
}
 
//remove方法移除eMyStudyEvent里面已存在的委托  
public void remove_eMyStudyEvent(MyStudyEvent value)
{
    MyStudyEvent event3;
    MyStudyEvent eMyStudyEvent = this.eMyStudyEvent;
    do
    {
        event3 = eMyStudyEvent;
        MyStudyEvent event4 = (MyStudyEvent)System.Delegate.Remove(event3, value);
        eMyStudyEvent = Interlocked.CompareExchange<MyStudyEvent>(ref this.eMyStudyEvent, event4, event3);
    }
    while (eMyStudyEvent != event3);
}

posted @ 2020-07-22 08:40 青蛙學堂 阅读(9) | 评论 (0)编辑 收藏

c# ?的作用

  之前最常用的也就是(?:),最近遇到(?)和(??)感觉还是挺有意思的。

1、可空类型修饰符(?)
int? a = null;

对比试试
int a = null;

2、空合并运算符(??)
     用于定义可空类型和引用类型的默认值。如果此运算符的左操作数不为null,则此运算符将返回左操作数,否则返回右操作数。
       例如:a ?? b 当a为null时则返回b,a不为null时则返回a本身。

string a = null;
string b = "b";
string c = "c";
var d = a ?? b ?? c;  //"b"
3、三元(运算符)表达式(?:)
   x?y:z 表示如果表达式x为true,则返回y;如果x为false,则返回z,是省略if{}else{}的简单形式。

string a = "a";
var b = a == "a" ? "a" : "b";  //"a"
4、具体使用案例:在不报异常的情况下取为null的lst中集合的个数
            List<string> lst = null;
            var a = lst?.Count ?? 0;  //0
            var b = lst == null ? 0 : lst.Count;  //0
————————————————
 

posted @ 2020-07-21 10:26 青蛙學堂 阅读(9) | 评论 (0)编辑 收藏

c# 泛型类语法


泛型将类型参数的概念引入 .NET,这样就可设计具有以下特征的类和方法:在客户端代码声明并初始化这些类或方法之前,这些类或方法会延迟指定一个或多个类型。 例如,通过使用泛型类型参数 T,可以编写其他客户端代码能够使用的单个类,而不会产生运行时转换或装箱操作的成本或风险,如下所示:

//泛型类语法
// Declare the generic class.
public class GenericList<T>
{   
   //参数
    public void Add(T input) { }
}
class TestGenericList
{
    private class ExampleClass { }
    static void Main()
    {
        // Declare a list of type int.
        GenericList<int> list1 = new GenericList<int>();
        list1.Add(1);

        // Declare a list of type string.
        GenericList<string> list2 = new GenericList<string>();
        list2.Add("");

        // Declare a list of type ExampleClass.
        GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
        list3.Add(new ExampleClass());
    }
}

泛型类和泛型方法兼具可重用性、类型安全性和效率,这是非泛型类和非泛型方法无法实现的。 泛型通常与集合以及作用于集合的方法一起使用。 System.Collections.Generic 命名空间包含几个基于泛型的集合类。 非泛型集合(如 ArrayList)不建议使用,并且保留用于兼容性目的。 有关详细信息,请参阅 .NET 中的泛型。

posted @ 2020-07-21 10:15 青蛙學堂 阅读(8) | 评论 (0)编辑 收藏

c# 泛型方法语法

泛型方法是通过类型参数声明的方法,如下所示:
C#

 
static void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}
如下示例演示使用类型参数的 int 调用方法的一种方式:
C#

 
public static void TestSwap()
{
    int a = 1;
    int b = 2;

    Swap<int>(ref a, ref b);
    System.Console.WriteLine(a + " " + b);
}
还可省略类型参数,编译器将推断类型参数。 如下 Swap 调用等效于之前的调用:
C#

 
Swap(ref a, ref b);
类型推理的相同规则适用于静态方法和实例方法。 编译器可基于传入的方法参数推断类型参数;而无法仅根据约束或返回值推断类型参数。 因此,类型推理不适用于不具有参数的方法。 类型推理发生在编译时,之后编译器尝试解析重载的方法签名。 编译器将类型推理逻辑应用于共用同一名称的所有泛型方法。 在重载解决方案步骤中,编译器仅包含在其上类型推理成功的泛型方法。
在泛型类中,非泛型方法可访问类级别类型参数,如下所示:
C#

 
class SampleClass<T>
{
    void Swap(ref T lhs, ref T rhs) { }
}

posted @ 2020-07-21 10:07 青蛙學堂 阅读(7) | 评论 (0)编辑 收藏

仅列出标题
共40页: 1 2 3 4 5 6 7 8 9 Last 
<2020年9月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿(7)

随笔分类

随笔档案

收藏夹

青蛙学堂

最新评论

阅读排行榜

评论排行榜