ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定

本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据。

 

在Models文件夹下创建Comment类:

 

namespace MvcApplication5.Models
{
    public class Comment
    {
        public int ID { get; set; }
        public string Author { get; set; }
        public string Text { get; set; }
        public string Email { get; set; }
    }
}

在Repository文件夹下创建ICommentRepository接口:

 

using System.Collections.Generic;
using MvcApplication5.Models;
namespace MvcApplication5.Repository
{
    public interface ICommentRepository
    {
        IEnumerable<Comment> Get();
        bool TryGet(int id, out Comment comment);
        Comment Add(Comment comment);
        bool Delete(int id);
        bool Update(Comment comment);
    }
}    

 

在Repository文件夹下创建CommentRepository类,实现ICommentRepository接口:

 

using  System.Collections.Generic;
using System.Linq;
using MvcApplication5.Models;
namespace MvcApplication5.Repository
{
    public class CommentRepository : ICommentRepository
    {
        private int nextID = 0;
        Dictionary<int, Comment>  comments = new Dictionary<int, Comment>();
        public CommentRepository()
        {
            Add(new Comment
            {
                ID = 1,
                Text = @"I sat here trying really hard to think of something profound to write for my comment but was left with nothing interesting to say other than this droning on and on that I'm doing right now. But sometimes, droning on and on serves a purpose. For example, this comment appears more realistic without resorting to Lorem Ipsum.",
                Author = "Phil",
                Email = "haacked@gmail.com",
            });
            Add(new Comment
            {
                ID = 1,
                Text = "This is the best thing I've ever seen! And trust me, I've seen a lot. A whole lot.",
                Author = "Henrik",
                Email = "henrikn@microsoft.com"
            });
            Add(new Comment
            {
                ID = 2,
                Text = "Is this thing on? Because if it isn't on, we should really consider turning it on. Have you tried turning it on? I haven't. But you should consider it.",
                Author = "Eilon",
                Email = "elipton@microsoft.com"
            });
            Add(new Comment
            {
                ID = 3,
                Text = "My computer's cupholder doesn't work, can you help? I tried calling tech support, but they keep laughing and I don't understand why. It's really not helpful.",
                Author = "Glenn",
                Email = "gblock@microsoft.com"
            }); 
        }
        public IEnumerable<Comment> Get()
        {
            return comments.Values.OrderBy(c => c.ID);
        }
        public bool TryGet(int id, out Comment comment)
        {
            return comments.TryGetValue(id, out comment);
        }
        public Comment Add(Comment comment)
        {
            comment.ID = nextID++;
            comments[comment.ID] = comment;
            return comment;
        }
        public bool Delete(int id)
        {
            return comments.Remove(id);
        }
        public bool Update(Comment comment)
        {
            bool update = comments.ContainsKey(comment.ID);
            comments[comment.ID] = comment;
            return update;
        }
    }
}

 

右键"引用",在"管理NuGet"程序包中搜索、安装Ninject。

1

 

在ASP.NET Web API中,DefaultHttpControllerActivator默认使用DependencyResolver对象去激活目标HttpControlle,通过实现IDependencyResolver接口可自定义DependencyResolver,从而把Ninject引入。

using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
using Ninject;
namespace MvcApplication5.Extension
{
    public class NinjectDependencyResolver : IDependencyResolver
    {
        private List<IDisposable> disposables = new List<IDisposable>();
        public IKernel Kernel { get; private set; }
        public NinjectDependencyResolver(NinjectDependencyResolver parent)
        {
            this.Kernel = parent.Kernel;
        }
        public NinjectDependencyResolver()
        {
            this.Kernel = new StandardKernel();
        }
        public void Register<TFrom, TTo>() where TTo : TFrom
        {
            this.Kernel.Bind<TFrom>().To<TTo>();
        }
        public IDependencyScope BeginScope()
        {
            return new NinjectDependencyResolver(this);
        }
        public object GetService(System.Type serviceType)
        {
            return this.Kernel.TryGet(serviceType);
        }
        public System.Collections.Generic.IEnumerable<object> GetServices(System.Type serviceType)
        {
            foreach (var service in this.Kernel.GetAll(serviceType))
            {
                this.AddDisposableService(service);
                yield return service;
            }
        }
        public void Dispose()
        {
            foreach (IDisposable disposable in disposables)
            {
                disposable.Dispose();
            }
        }
        private void AddDisposableService(object service)
        {
            IDisposable disposable = service as IDisposable;
            if (disposable != null && !disposables.Contains(disposable))
            {
                disposables.Add(disposable);
            }
        }
    }
}

 

在全局注册NinjectControllerFactory这个自定义控制器工厂。

 

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            ......
            NinjectDependencyResolver dependencyResolver = new NinjectDependencyResolver();
            dependencyResolver.Register<ICommentRepository, CommentRepository>();
            GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver; 
        }


创建名称为CommentsController空的API控制器,编写如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MvcApplication5.Models;
using MvcApplication5.Repository;
using Ninject;
namespace MvcApplication5.Controllers
{
    public class CommentsController : ApiController
    {
        [Inject]
        public ICommentRepository CommentRepository { get; set; }
        #region 获取数据
        public IEnumerable<Comment> GetComments()
        {
            return CommentRepository.Get();
        }
        public Comment GetComment(int id)
        {
            Comment comment;
            if (!CommentRepository.TryGet(id, out comment))
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
            return comment;
        }
        #endregion
    }
}

 

在HomeController中提供一个Index视图。

 

using System.Web.Mvc;
namespace MvcApplication5.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

 

在Shared/_Layout.cshtml中:

 

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    <link href="~/Content/Demo.css" rel="stylesheet" />
</head>
<body>
    @RenderBody()
    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>

在Home/Index.cshtml视图中,通过Knockout在页面元素和页面视图模型间实现双向绑定,通过jQuery把从后台获取到的集合赋值给前端的页面视图模型的comments字段,遍历页面视图模型的comments,使用模版把内容显示出来。
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
    <button id="getComments">获取评论</button>
</div>
<ul data-bind="template: { name: 'commentTemplate', foreach: comments }"> 
</ul> 
@section scripts
{
    <script src="~/Scripts/knockout-2.2.0.js"></script>
    <script type="text/javascript">
        viewModel = {
            comments: ko.observableArray([])
        };
        ko.applyBindings(viewModel);
        $(function() {
            $('#getComments').on("click", function() {
                viewModel.comments([]);
                $.get('/api/comments', function (data) {
                    viewModel.comments(data);
                });
            });
        });
    </script>
    <script id="commentTemplate" type="text/html">
        <li class="comment">
            <header>
                <div class="info">
                    <strong><span data-bind="text: Author"></span></strong>
                </div>
            </header>
            <div class="body">
                <p data-bind="text: Text"></p>
            </div>
        </li>
    </script>
}

2


参考资料:
http://www.cnblogs.com/artech/p/ioc-4-asp-net-web-api.html
https://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7/sourcecode?

posted @ 2015-02-11 13:18  Darren Ji  阅读(960)  评论(0编辑  收藏  举报

我的公众号:新语新世界,欢迎关注。