欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET Web API & Backbone (1) —— Web API & Simple Get

程序员文章站 2023-01-28 22:14:36
这个系列主要介绍如何使用Backbone搭建基于 ASP.NET Web API 的客户端(重点在于Backbone的使用)    .NET 4.5 中的...
这个系列主要介绍如何使用Backbone搭建基于 ASP.NET Web API 的客户端(重点在于Backbone的使用)

 

 .NET 4.5 中的 ASP.NET Web API 使得我们可以快速搭建基于REST风格的服务应用,利用强大的客户端框架 Backbone 我们可以采用MVC的设计思路,

组织客户端Javascript模块(功能) 从而实现快速灵活的应用开发。

 

 

 

 

 

【服务端 Web API】

为了演示我设计了一个简单的应用:留言簿

首先是服务端的 Model:

 

 

[csharp] 

namespace BackboneAndWebApi.Models  

{  

    public class Comment  

    {  

        public Comment() { }  

  

        public Comment(string text, string author)  

        {  

            Text = text;  

            Author = author;  

        }  

  

        public int ID { get; set; }  

  

        [Required]  

        public string Text { get; set; }  

  

        [Required]  

        [StringLength(10, ErrorMessage = "Author is too long! This was validated on the server.")]  

        public string Author { get; set; }  

  

        [Required]  

        public string Email { get; set; }  

  

        public string GravatarUrl  

        {  

            get  

            {  

                return HttpUtility.HtmlDecode(Gravatar.GetUrl(Email ?? "", 40, defaultImage: "retro", rating: GravatarRating.G));  

            }  

            set { }  

        }  

    }  

}  

 

namespace BackboneAndWebApi.Models

{

    public class Comment

    {

        public Comment() { }

 

        public Comment(string text, string author)

        {

            Text = text;

            Author = author;

        }

 

        public int ID { get; set; }

 

        [Required]

        public string Text { get; set; }

 

        [Required]

        [StringLength(10, ErrorMessage = "Author is too long! This was validated on the server.")]

        public string Author { get; set; }

 

        [Required]

        public string Email { get; set; }

 

        public string GravatarUrl

        {

            get

            {

                return HttpUtility.HtmlDecode(Gravatar.GetUrl(Email ?? "", 40, defaultImage: "retro", rating: GravatarRating.G));

            }

            set { }

        }

    }

}当然要有增删改查,于是有了下面的 Repository 接口

[csharp] 

namespace BackboneAndWebApi.Models  

{  

    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);  

    }  

}  

 

namespace BackboneAndWebApi.Models

{

    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);

    }

}具体实现采用内存数据存储:

[csharp] 

namespace BackboneAndWebApi.Models  

{  

  

    public class DictionaryCommentRepository : ICommentRepository  

    {  

        int nextID = 0;  

        Dictionary<int, Comment> comments = new Dictionary<int, Comment>();  

  

        public IEnumerable<Comment> Get()  

        {  

            return comments.Values.OrderBy(comment => comment.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;  

        }  

    }  

}  

 

namespace BackboneAndWebApi.Models

{

 

    public class DictionaryCommentRepository : ICommentRepository

    {

        int nextID = 0;

        Dictionary<int, Comment> comments = new Dictionary<int, Comment>();

 

        public IEnumerable<Comment> Get()

        {

            return comments.Values.OrderBy(comment => comment.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;

        }

    }

}利用 Ninject 在 WebAPI 初始化时注入(InitialData 是 DictionaryCommentRepository 的子类,构造函数中加一些初始数据)

[csharp] 

namespace BackboneAndWebApi  

{  

    public static class WebApiConfig  

    {  

        public static void Register(HttpConfiguration config)  

        {  

            config.Filters.Add(new ValidateAttribute());  

  

            IKernel kernel = new StandardKernel();  

            kernel.Bind<ICommentRepository>().ToConstant(new InitialData());  

            config.DependencyResolver = new NinjectResolver(kernel);  

  

            config.Routes.MapHttpRoute(  

                name: "DefaultApi",  

                routeTemplate: "api/{controller}/{id}",  

                defaults: new { id = RouteParameter.Optional }  

            );  

        }  

    }  

}  

 

namespace BackboneAndWebApi

{

    public static class WebApiConfig

    {

        public static void Register(HttpConfiguration config)

        {

            config.Filters.Add(new ValidateAttribute());

 

            IKernel kernel = new StandardKernel();

            kernel.Bind<ICommentRepository>().ToConstant(new InitialData());

            config.DependencyResolver = new NinjectResolver(kernel);

 

            config.Routes.MapHttpRoute(

                name: "DefaultApi",

                routeTemplate: "api/{controller}/{id}",

                defaults: new { id = RouteParameter.Optional }

            );

        }

    }

}

CommentsController 是 Web API 的实现类,实现了简单的GET

[csharp]

namespace BackboneAndWebApi.Controllers  

{  

    public class CommentsController : ApiController  

    {  

        ICommentRepository repository;  

  

        public CommentsController(ICommentRepository repository)  

        {  

            this.repository = repository;  

        }  

 

        #region GET   

        [Queryable]  

        public IQueryable<Comment> GetComments()  

        {  

            return repository.Get().AsQueryable();  

        }  

  

        public Comment GetComment(int id)  

        {  

            Comment comment;  

            if (!repository.TryGet(id, out comment))  

                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));  

            return comment;  

        }  

        #endregion   

    }  

}  

 

namespace BackboneAndWebApi.Controllers

{

    public class CommentsController : ApiController

    {

        ICommentRepository repository;

 

        public CommentsController(ICommentRepository repository)

        {

            this.repository = repository;

        }

 

        #region GET

        [Queryable]

        public IQueryable<Comment> GetComments()

        {

            return repository.Get().AsQueryable();

        }

 

        public Comment GetComment(int id)

        {

            Comment comment;

            if (!repository.TryGet(id, out comment))

                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));

            return comment;

        }

        #endregion

    }

}

发布后,用Fiddler测试(别忘记加上 Accept: application/json 的Header,这样才会返回json格式的数据)

 

ASP.NET Web API & Backbone (1) —— Web API & Simple Get

【客户端】

先加入 Backbone,可以上官网自己下载,或者直接用 Nuget : Install-Package Backbone.js 

通过下面的 HTML 可以对 Backbone 进行初步的理解:

这个“留言簿” 定义为 CommentModel 和 CommentView,View负责页面的描绘,Model则是对应服务端实体,model.fetch 取得数据,view.render 将取到的数据交给

underscore 的 template 生成HTML结果。其他一些细节请看下面代码中的注释。

[html] 

<!DOCTYPE html>  

<html>  

<head>  

    <meta charset="utf-8" />  

    <title>Comments Test Home Page</title>  

    <link href="/Content/Demo.css" rel="stylesheet" type="text/css" />  

    <script src="Scripts/jquery-1.9.0.min.js"></script>  

    <script src="Scripts/underscore-1.4.3.js"></script>  

    <script src="Scripts/backbone-0.9.9.js"></script>  

</head>  

<body>  

    <nav>  

        <p class="demo-navigation">  

            <a href="default.htm"><<< Back</a>   

            | Demo 1 Simple Get |  

            <a href="demo2-crud.htm">On to Demo 2 - Simple CRUD >>></a>  

        </p>  

    </nav>  

    <p id="content">  

          

        <p id="demo-actions">  

            <p>  

                <legend>Get Comments Demos</legend>  

                <button id="getComments">Go!</button>  

            </p>  

        </p>  

        <p id="article">  

            <p>  

                This first demo shows a very simple GET scenario. Click on the button to   

                use jQuery to retrieve JSON data from a Web API endpoint and then display   

                the contents of that payload in the UI.  

            </p>  

            <p>  

                The code represents retrieving data in a manner that any developer familiar   

                with jQuery would understand.  

            </p>  

        </p>  

  

        <ul id="comments">  

        </ul>  

  

        <!-- 模板 -->  

        <script id="commentTemplate" type="text/html">  

          <% _.each(comments, function(item) { %>  

            <li class="comment">  

                <header>  

                  <p class="info">  

                    <img src='<%= item.GravatarUrl %>' />  

                    <strong><span><%= item.Author %></span></strong>  

                  </p>  

                </header>  

                <p class="body">  

                  <p><%= item.Text %></p>  

                </p>  

            </li>  

          <% }); %>  

        </script>  

  

        <script type="text/javascript">  

            var CommentModel = Backbone.Model.extend({  

                // model 对应服务端的API URL  

                url: 'api/comments'  

            });  

            var CommentView = Backbone.View.extend({  

                // 将body作为一个View   

                el: 'body',  

                // 加载模板  

                template: _.template($('#commentTemplate').html()),  

                // 绑定HTML上"Go!"按钮,调用 model.fetch 获取数据  

                // model.fetch 会调用 Backbone.sync('read', model, options) 里面封装了ajax  

                events: {  

                    'click #getComments': function () {  

                        this.model.fetch();  

                    }  

                },  

                initialize: function () {  

                    this.model.on('change', this.render, this);  

                },  

                render: function () {  

                    var data = this.model.toJSON();  

                    $('#comments').html(this.template({ comments: data }));  

                    return this;  

                }  

            });  

              

            $(function () {  

                var view = new CommentView({ model: new CommentModel() });  

            });  

        </script>  

    </p>  

</body>  

</html>  

 

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <title>Comments Test Home Page</title>

    <link href="/Content/Demo.css" rel="stylesheet" type="text/css" />

    <script src="Scripts/jquery-1.9.0.min.js"></script>

    <script src="Scripts/underscore-1.4.3.js"></script>

    <script src="Scripts/backbone-0.9.9.js"></script>

</head>

<body>

    <nav>

        <p class="demo-navigation">

            <a href="default.htm"><<< Back</a> 

            | Demo 1 Simple Get |

            <a href="demo2-crud.htm">On to Demo 2 - Simple CRUD >>></a>

        </p>

    </nav>

    <p id="content">

        

        <p id="demo-actions">

            <p>

                <legend>Get Comments Demos</legend>

                <button id="getComments">Go!</button>

            </p>

        </p>

        <p id="article">

            <p>

                This first demo shows a very simple GET scenario. Click on the button to 

                use jQuery to retrieve JSON data from a Web API endpoint and then display 

                the contents of that payload in the UI.

            </p>

            <p>

                The code represents retrieving data in a manner that any developer familiar 

                with jQuery would understand.

            </p>

        </p>

 

        <ul id="comments">

        </ul>

 

        <!-- 模板 -->

        <script id="commentTemplate" type="text/html">

          <% _.each(comments, function(item) { %>

            <li class="comment">

                <header>

                  <p class="info">

                    <img src='<%= item.GravatarUrl %>' />

                    <strong><span><%= item.Author %></span></strong>

                  </p>

                </header>

                <p class="body">

                  <p><%= item.Text %></p>

                </p>

            </li>

          <% }); %>

        </script>

 

        <script type="text/javascript">

            var CommentModel = Backbone.Model.extend({

                // model 对应服务端的API URL

                url: 'api/comments'

            });

            var CommentView = Backbone.View.extend({

                // 将body作为一个View 

                el: 'body',

                // 加载模板

                template: _.template($('#commentTemplate').html()),

                // 绑定HTML上"Go!"按钮,调用 model.fetch 获取数据

                // model.fetch 会调用 Backbone.sync('read', model, options) 里面封装了ajax

                events: {

                    'click #getComments': function () {

                        this.model.fetch();

                    }

                },

                initialize: function () {

                    this.model.on('change', this.render, this);

                },

                render: function () {

                    var data = this.model.toJSON();

                    $('#comments').html(this.template({ comments: data }));

                    return this;

                }

            });

            

            $(function () {

                var view = new CommentView({ model: new CommentModel() });

            });

        </script>

    </p>

</body>

</html>运行结果:

 

ASP.NET Web API & Backbone (1) —— Web API & Simple Get