2013年8月13日星期二

ASP.NET MVC 4使用技巧8:自定义CheckBox及ActionResult的Subtypes

今天简单介绍一下如何编写一个自定义的CheckBox:

<script type="text/javascript">
    function unhide(id_name, check_box) {
        var check = (check_box.checked) ? "block" : "none";
        document.getElementById(id_name).style.display = check;
    }
</script>



@Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
<div id="hidden-input-email" style="display:none">
<p>
   @Html.LabelFor(model => model.Email) 
   @Html.TextBoxFor(model => model.Email, new { @readonly="readonly" })
</p>
<div class="editor-field">
   @Html.TextAreaFor(model => model.EmailInfos, new { style = "width: 200px; height: 100px;" })
</div>


       
上面的View代码,使用了自定义的CheckBox
简单的说明一下:

  1. @Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
  2. 当我们点击这个CheckBox的时候会将隐藏的输入框显示出来,这里使用了一个简单的Javascript,当@onclick的事件被触发时。
  3. 同时这里使用@checked = "unchecked"设置初始为unchecked。
  4. 参数:model => model.NotifyEmail是我们对于checkbox的view model binding。
  5. 我们的TextAreaFor也通过参数:new { style = "width: 200px; height: 100px;" }自定义了大小。

 

ActionResult有很多种Subtypes,我今天才知道,以前只用过3种。
出处:http://forums.asp.net/t/1448398.aspx


       
ViewResult - Renders a specifed view to the response stream

PartialViewResult - Renders a specifed partial view to the response stream

EmptyResult - An empty response is returned

RedirectResult - Performs an HTTP redirection to a specifed URL

RedirectToRouteResult - Performs an HTTP redirection to a URL that is determined by the routing engine, based on given route data

JsonResult - Serializes a given ViewData object to JSON format

JavaScriptResult - Returns a piece of JavaScript code that can be executed on the client

ContentResult - Writes content to the response stream without requiring a view

FileContentResult - Returns a file to the client

FileStreamResult - Returns a file to the client, which is provided by a Stream

FilePathResult - Returns a file to the client       

2013年8月11日星期日

ASP.NET MVC 4使用技巧7:加入角色(Roles.AddUserToRoles)和使用者授权

加入角色

1. 加入角色信息到webpages_Roles表中

我们可以在Server Explorer中非常方便地加入角色信息进入webpages_Roles表,如下图所示:

howto_show_table_data

然后加入信息,如下图所示,我们加入5种角色。

webpages_roles_table

2. 在Controller中给注册的用户信息加入角色,需要使用到Roles.AddUserToRoles方法,具体可以参阅:

http://msdn.microsoft.com/en-us/library/system.web.security.roles.addusertoroles.aspx

在下面的例子中,我们在Register方法(位于AccountController.cs中)使用了Roles.AddUserToRoles方法(它也就是一个User, Roles, and Membership static classes ),将得到的model的role信息存入,这里需要对应model和view,关于register的model和view这里就不多写了。

[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
    your code…. your code
             string choosenRole;
                if (model.Position == 0)
                    choosenRole = "Admin";
                else if (model.Position == 1)
                    choosenRole = "Planer";
                else if (model.Position == 2)
                    choosenRole = "Controller";
                else if (model.Position == 3)
                    choosenRole = "Manager";
                else
                    choosenRole = "Employee";

                System.Web.Security.Roles.AddUserToRole(model.UserName, choosenRole);
    WebSecurity.Login(model.UserName, model.Password);

                return RedirectToAction("Index", "Home");
            }
your code  your code
return View(model);
}

使用者授权


需要使用membership的role控制这样才能使用,很简单我们使用[Authorize]修饰词

譬如
[Authorize(Roles = "Admin,Manager")]

或者
[Authorize(Roles = "Manager")]

[Authorize(Roles = "Admin")]

也可以限定用户,譬如

[Authorize(User="Alex")] 

譬如在HomeController.cs中:

[Authorize(Roles = "Manager")]
public ActionResult Contact()
{
    ViewBag.Message = "";
    return View();
}

2013年8月9日星期五

ASP.NET MVC 4使用技巧6:Bundle和fullcalendar

fullcalendar是我见过最好的开源jQuery plugin,提供drag & drop calendar功能,而且是使用MIT license

1. 下载fullcalendar,先将所有需要的东西放入Scripts和Content文件夹里

2. 设置BundleConfig.cs

在App_Start可以找到BundleConfig.cs

加入

bundles.Add(new ScriptBundle("~/bundles/calendar").Include("~/Scripts/fullcalendar.min.js"));

bundles.Add(new StyleBundle("~/Content/calendar").Include(
                           "~/Content/fullcalendar.css"));

其中("~/bundles/calendar")为初始化的虚拟目录,它的名称不能跟真正的目录相同 也就是 后面的Include里的目录。

3. 在譬如\Views\Shared\_testLayout.cshtml中加入fullcalendar的css和其需要的js库。

需要加入以下两行代码:

@Styles.Render("~/Content/calendar") //就是 calling "~/Content/fullcalendar.css"。

@Scripts.Render("~/bundles/fullcalendar") //就是 calling "~/Scripts/fullcalendar.min.js"。

注意,导入js库的顺序,否则将不能使用,最后导入fullcalendar。

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/fullcalendar")
@RenderSection("scripts", required: false)
 

有两个要点需要注意的:a. 要将它们放入<header> </header>中,而不是<body> </body>中延迟调用。

b. 注意如果要实现drag & drop calendar功能,需要使用<script src='~/Script/jquery-ui-1.10.2.custom.min.js'></script>,这可以加入到<header> </header>,当然也可以使用bundles。

4. 这时候可以添加View,选择Use a layout or master page,在下拉菜单中可以选择我们刚刚做的_testLayout.cshtml,最后在生成的view加入

<div id='calendar'></div>    

就可以了,现在可以看到一个空的calendar。

5. 最后我们使用MVC,我们需要编写model和controller,生成json的events传递给calendar,以下代码来自于http://szahariev.blogspot.de/2009/08/jquery-fullcalendar-and-aspnet-mvc.html

Model:

public class CalendarDTO
{
    public int id { get; set; }
    public string title { get; set; }
    public long start { get; set; }
    public long end { get; set; }
    public string url { get; set; }
}

 

Controller:

public ActionResult CalendarData()
{
    IList<CalendarDTO> tasksList = new List<CalendarDTO>();

    tasksList.Add(new CalendarDTO
    {
        id = 1,
        title = "test",
        start = ToUnixTimespan(DateTime.Now),
        end = ToUnixTimespan(DateTime.Now.AddHours(4)),
        url = ""
    });

    return Json(tasksList, JsonRequestBehavior.AllowGet);

    //return View();
}

private long ToUnixTimespan(DateTime date)
{
    TimeSpan tspan = date.ToUniversalTime().Subtract(
    new DateTime(1970, 1, 1, 0, 0, 0));

    return (long)Math.Truncate(tspan.TotalSeconds);
}

 

6. 最后在view里面加一个js funcution,就完成了

View:

<script type="text/javascript">
       $(document).ready(function() {
           $('#calendar').fullCalendar({
               events: "/YourControllerName/CalendarData"
           });
       });  
 </script>

<div id="calendar">
</div>

2013年8月7日星期三

ASP.NET MVC 4使用技巧5:SQL命令

在这篇文章简要介绍SQL在C#中的使用,和MVC没有太大关系。

需要:

using System.Configuration;
using System.Data.SqlClient;

譬如,Controller中的一个方法

public ActionResult Information()
{
      string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
      List<string> users = new List<string>();
      using (SqlConnection conn = new SqlConnection(connectionString))
      {
              // Open the connection
            conn.Open();
            string sql = "SELECT * FROM UserProfile";
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    users.Add(reader["UserName"].ToString());
                }
                reader.Close();  
            }
            conn.Close();
       }
       ViewBag.Message = "Info";
       return View(users);
}

先总体简要解释一下以上Controller方法代码:

其实一般而言,基本SQL操作需要以下5步,这里还是以上面的代码为例进行介绍:

1. 连接服务器

string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

using (SqlConnection conn = new SqlConnection(connectionString))

conn.Open();

2.SQL 字符串赋值(需要执行的sql命令)

string sql = "SELECT * FROM UserProfile";

3. 新建命令

using (SqlCommand cmd = new SqlCommand(sql, conn))

4. 执行命令

分为三种命令,相应调用不同的方法:

a 不需要查询的(插入,更新,删除)

cmd.ExecuteNonQuery();

该函数会返回收到影响的总行数。

b 只需要查询一个值的

cmd.ExecuteScalar();

该函数会返回使用的sql语言查询的结果

譬如:

string user_name = "John";

var sql = String.Format("SELECT Company FROM UserProfile WHERE [UserName] = '{0}'", user_name);

using (SqlCommand cmd = new SqlCommand(sql, conn))

{

    string test = cmd.ExecuteScalar().ToString();

}

c 需要同时查询得到多个值的

//新建一个SqlDataReader 

SqlDataReader  reader = cmd.ExecuteReader(); 

//读取一行数据到Reader中

(reader.Read())

{

//将Reader中的数据读取走

users.Add(reader["UserName"].ToString());

}

//关闭Reader

reader.Close();  


5. 关闭连接
conn.Close();

更多内容请参考:

http://www.dotnetperls.com/sqlcommand

2013年8月6日星期二

ASP.NET MVC 4使用技巧4:从controller到view传递information的方法

其实有三个方法用于传递information

    • 使用 strongly typed model object
    • 使用 ViewBag
    • 使用 dynamic type (using @model dynamic)

本来要用自己的例子,但是找到几个非常有趣的例子,来自于《Pro asp.net mvc 4 4th edition》,这里做一个引用。

关于strongly typed model object,请参考:

http://www.asp.net/mvc/tutorials/views/dynamic-v-strongly-typed-views

或《Pro asp.net mvc 4 4th edition》31页

 

关于ViewBag,它其实是一个dynamic object可以用于赋值。

以下代码源于《Pro asp.net mvc 4 4th edition》26页

Controller:

1 public class HomeController : Controller {
2 public ViewResult Index() {
3     int hour = DateTime.Now.Hour;
4     ViewBag.Greeting = hour < 12 ? "Good Morning" : "Good Afternoon";
5     return View();
6     }
7 }

View:

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
10 <body>
11 <div>
12     @ViewBag.Greeting World (from the view)
13 </div>
14 </body>
15 </html>

 

关于用dynamic type (using @model dynamic)

以下代码子源于《Pro asp.net mvc 4 4th edition》35页

Model:

1 namespace PartyInvites.Models {
2     public class GuestResponse {
3     public string Name { get; set; }
4     public string Email { get; set; }
5     public string Phone { get; set; }
6     public bool? WillAttend { get; set; }
7     }
8 }

其中WillAttend为nullable bool,也就是它的值可以为true,false或者为null。

Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PartyInvites.Models;
namespace PartyInvites.Controllers {
public class HomeController : Controller {
    public ViewResult Index() {
10         int hour = DateTime.Now.Hour;
11         ViewBag.Greeting = hour < 12 ? "Good Morning" : "Good Afternoon";
12         return View();
13     }
14     [HttpGet]
15     public ViewResult RsvpForm() {
16         return View();   
17     }
18     [HttpPost]
19     public ViewResult RsvpForm(GuestResponse guestResponse) {
20         // TODO: Email response to the party organizer
21         return View("Thanks", guestResponse);
22     }
23 }
24 }

注意的是HttpGet attribute和HttpPost attribute,告诉method是处理get还是post。

View: RsvpForm.cshtml

@model PartyInvites.Models.GuestResponse
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>RsvpForm</title>
10 </head>
11 <body>
12 @using (Html.BeginForm()) {
13     <p>Your name: @Html.TextBoxFor(x => x.Name) </p>
14     <p>Your email: @Html.TextBoxFor(x => x.Email)</p>
15     <p>Your phone: @Html.TextBoxFor(x => x.Phone)</p>
16     <p>
17     Will you attend?
18         @Html.DropDownListFor(x => x.WillAttend, new[] {
19         new SelectListItem() {Text = "Yes, I'll be there",
20         Value = bool.TrueString},
21         new SelectListItem() {Text = "No, I can't come",Value = bool.FalseString}
22         }, "Choose an option")
23         </p>
24         <input type="submit" value="Submit RSVP" />
25     }
26 </body>
27 </html>

 

View: Thanks.cshtml

@model PartyInvites.Models.GuestResponse
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Thanks</title>
10 </head>
11 <body>
12 <div>
13 <h1>Thank you, @Model.Name!</h1>
14     @if (Model.WillAttend == true) {
15     @:It's great that you're coming. The drinks are already in the fridge!
16     } else {
17     @:Sorry to hear that you can't make it, but thanks for letting us know.
18     }
19 </div>
20 </body>
21 </html>