2009年10月23日 星期五

ModelBinder In Asp.Net MVC

What is ModelBinder.
在 MSDN 中是這麼定義的

IModelBinder
Defines the methods that are required for a model binder.亙 費話

ModelBinder在 ASP.NET 中最主要的作用是讓POST回來的值在進入 Cotroller 之前可以先做一點整理。讓 Controller 可以直接使用已整理後的 Class 而不是一堆 Form 上面的資料

How.
要使用 ModelBinder 有幾個步驟
1. 建立 ModelBinder, 要 Implement IModelBinder
    public class Service1ModelBinder : IModelBinder
    {
        #region IModelBinder Members
 
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;
 
            Service1 service = new Service1(new User())
            {
                Name = request["name"]

..... other fields you need

            };
 
            return service;
        }
 
        #endregion
    }

2.定義 這個 ModelBinder 是 Bind 那個Class,這個要寫在 HttpApplication 中,一般是 Global.asax.cs

        protected void Application_Start()
        {

            //ModelBinders
            ModelBinderDictionary binders = System.Web.Mvc.ModelBinders.Binders;
            binders[typeof(Service1)] = new Service1ModelBinder();
            RegisterRoutes(RouteTable.Routes);
        }

3. 改寫 Controller 的 method

        [AcceptVerbs("POST")]
        public ActionResult Index(Service1 service)
        {
            ViewData["Message"] = service.Name;
 
            return View();
        }
View 的 code 如下
    <% Html.BeginForm(); %>
        <input type="text" name="name" value="Service1" />
        <button type="submit">Submitbutton>
    <%Html.EndForm(); %>

如此一來,在我們按下按鈕時會先觸發 ModelBinder 再將 ModelBinder 過後的 object 送給 Controller

Reference

IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing


IModelBinder Interface

2009年10月21日 星期三

Unity 學習筆記 in Asp.Net MVC

1.Container.Resolve(Type t)
Resolve an instance of the default requested type from the container.
會將所指定的 class 產生一個 instance 並且將 Constructor 中的 parameter 注入

        container.Resolve(typeof(HomeController))

        public HomeController(Service service, Service2 service2)
        {
            this.service = service;
            this.service2 = service2;
        }

container 會將 Service 及 Service2 注入到 HomeController 中
但有個地方值得注意的。就是如果 HomeController 的 Constructor parameter 的 type 是 interface 時,就必需要注冊
            container.RegisterType<IService, Service>();

否則會有錯誤產生

2. Singleton
底下以 RegisterInstance 的方來來注冊 IUser

        protected void Application_Start()
        {
            IUnityContainer container = new UnityContainer();
 
            container.RegisterInstance<IUser>(new User() { Name = "Unity" });
 
 
            CustomUnityControllerFactory factory = new CustomUnityControllerFactory(container);
 
 
            ControllerBuilder.Current.SetControllerFactory(factory);
 
            RegisterRoutes(RouteTable.Routes);
        }

HomeController
Constructor 中有兩個參數 Service1, Service2
    [HandleError]
    public class HomeController : Controller
    {
        Service1 service1;
        Service2 service2;
 
        public HomeController(Service1 service1, Service2 service2)
        {
            this.service1 = service1;
            this.service2 = service2;
        }
 
        public ActionResult Index()
        {
            ViewData["Message"] = service1.Message();
 
            ViewData["Message2"] = service2.Message();
 
            return View();
        }
 
        public ActionResult About()
        {
            return View();
        }
 
    }

Service1
在呼叫 Message 後會改變 User.Name 的值
    public class Service1 : IService
    {
        IUser user;
 
        public Service1(IUser user)
        {
            this.user = user;
        }
 
 
        #region IService Members
 
 
        public string Message()
        {
            string t = user.Name;
            user.Name = "Yes!! I'm Sigleton";
            return t;
        }
 
        #endregion
    }

Service2
    public class Service2 : IService
    {
        IUser user;
 
        public Service2(IUser user)
        {
            this.user = user;
        }
 
        #region IService Members
 
        public string Message()
        {
            return user.Name;
        }
 
        #endregion
    }
需注意的是 在 Service 的 constructor 中需以 IUser ,如以Class 來當為參數的話。unity會產生一個新的實體。


Reference
Unity framework with ASP.Net MVC Framework

2009年4月24日 星期五

Project to Posts ( Link to Sql sample)

由資料庫 投射到 實體的範例
在 oxite.LinqToSqlDataProvider 中的 PageRepository.cs
要 學起來

        private IQueryable<Page> projectPages(IQueryable<oxite_Post> posts)
        {
            return from p in posts
                   join u in context.oxite_Users on p.CreatorUserID equals u.UserID
                   let c = getCommentsQuery(p.PostID)
                   where p.State != (byte)EntityState.Removed
                   orderby p.PublishedDate descending
                   select new Page
                   {
                       ID = p.PostID,
                       Parent = getParentPage(p),
                       HasChildren = getHasChildren(p),
                       Creator = new User
                       {
                           DisplayName = u.DisplayName,
                           Email = u.Email,
                           HashedEmail = u.HashedEmail,
                           ID = u.UserID,
                           LanguageDefault = new Language
                           {
                               ID = u.oxite_Language.LanguageID,
                               DisplayName = u.oxite_Language.LanguageDisplayName,
                               Name = u.oxite_Language.LanguageName
                           },
                           Name = u.Username,
                           Status = u.Status,
                       },
                       Body = p.Body,
                       BodyShort = p.BodyShort,
                       Comments = new LazyList<Comment>(c),
                       Created = p.CreatedDate,
                       Modified = p.ModifiedDate,
                       Published = p.PublishedDate,
                       Slug = p.Slug,
                       State = (EntityState)p.State,
                       Title = p.Title,
                       CommentingDisabled = p.CommentingDisabled
                   };
        }

2009年1月7日 星期三

solve!! jquery datepicker problem

昨天遇到有關 datepicker 的問題
今天解決了!! 先來大笑三聲 哈哈哈~~~

先來還原現場

index.html
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
 
    <script src="jquery-1.2.6.min.js" type="text/javascript"></script>
 
    <script src="jquery-ui-packed.js" type="text/javascript"></script>
 
    <script type="text/javascript">
        $(function() {
            $("#btnLoad").click(function() {
                $("#pnlToLoad").load("form.html");
                $("form", "#pnlToLoad").dialog();
            });
        });
    </script>
 
</head>
<body>
    <div id="pnlToLoad" style="display: none">
        load</div>
    <input id="btnLoad" type="button" value="load" />
</body>
</html>


form.html
<form>
<input type="text" id="text1" onfocus="attachDatepicker(this)" />
</form>
 
<script type="text/javascript">
    function attachDatepicker(sender) {
        alert("!!");
        $(sender).datepicker();
    }
</script>
 



看出問題了嗎??

問題出現在 這

$("form", "#pnlToLoad").dialog();


就是在 index.html 中的這一行

因為我想讓 form load 完成後變成一個 dialog 出現
結果沒想到 dialog 會將 form 在 dom 裡面的位置改變
結果等於我按一下 load 在 dom 中就會再多一個 form 出現而且裡面 textbox 的 id 都是相同的
這樣子 jquery 的 selector 當然找不到想要的 input


改成這樣子就好了

$("#pnlToLoad").dialog();

jquery datepicker problem

最近試著使用 jquery 結合 asp.net 的專案
使用了大量的 $().load() 來載入 form 及 grid

但遇到了一個問題
datepicker 在第一次載入時可以正常執行

但在 form 第二次 load 之後
datepicker 怎樣都無法正確的將值放入 Textbox 中

似乎是因為 form 裡面Input 的 id 全都是一樣的。
所以jQuery 的 Selector 無法正確的找到新的 Textbox

目前還不知該如何解決

2009年1月5日 星期一

ASP.NET MVC on iis 6

Using ASP.NET MVC with Different Versions of IIS

1. Right-click a website and select Properties
2. Select the Home Directory tab
3. Click the Configuration button
4. Select the Mappings tab
5. Click the Insert button (see Figure 4)
6. Paste the path to the aspnet_isapi.dll into the Executable field (you can copy this path from the script map for .aspx files)
7. Uncheck the checkbox labeled Verify that file exists
8. Click the OK button