ASP.NET Web API实践系列02,在MVC4下的一个实例, 包含EF Code First,依赖注入, Bootstrap等

本篇体验在MVC4下,实现一个对Book信息的管理,包括增删查等,用到了EF Code First, 使用Unity进行依赖注入,前端使用Bootstrap美化。先上最终效果:

→创建一个MVC4项目,选择Web API模版。

→在Models文件夹创建一个Book.cs类。

namespace MyMvcAndWebApi.Models
{
    public class Book
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

→在Models文件夹创建BookInitializer类,用来初始化数据库表数据。

using System.Data.Entity;

namespace MyMvcAndWebApi.Models
{
    public class BookInitializer : DropCreateDatabaseIfModelChanges<BookStore>
    {
        protected override void Seed(BookStore context)
        {
            context.Books.Add(new Book() {Name = "我有一头小毛驴", Price = 200M});
            context.Books.Add(new Book() { Name = "今天天气真好", Price = 300M });
            context.Books.Add(new Book() { Name = "秋天是落叶的季节", Price = 500M });
        }
    }
}


→在Models文件夹中,创建BookStore类,派生于DbContext。

using System.Data.Entity;

namespace MyMvcAndWebApi.Models
{
    public class BookStore : DbContext
    {
        public BookStore() : base("conn")
        {
            Database.SetInitializer(new BookInitializer());
        }
       public  DbSet<Book> Books { get; set; }
    }
}


→在Web.config中配置连接字符串。

  <connectionStrings>
    ......
   <add name="conn" connectionString="Data Source=.;User=yourusername;Password=yourpassword;Initial Catalog=BookStore;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

→Repository首先需要一个接口,在Models文件夹中创建IBookRepository接口。

using System.Collections.Generic;

namespace MyMvcAndWebApi.Models
{
    public interface IBookRepository
    {
        IEnumerable<Book> GetAll();
        Book Get(int id);
        Book Add(Book book);
        void Remove(int id);
        bool Update(Book book);
    }
}

→实现IBookRepository接口,用到BookStore这个上下文。

using System.Collections.Generic;
using System.Data;

namespace MyMvcAndWebApi.Models
{
    public class BookRepository : IBookRepository
    {
        private BookStore db = new BookStore();

        public BookRepository(){}

        public IEnumerable<Book> GetAll()
        {
            return db.Books;
        }

        public Book Add(Book book)
        {
            db.Books.Add(book);
            db.SaveChanges();
            return book;
        }

        public void Remove(int id)
        {
            Book book = db.Books.Find(id);
            db.Books.Remove(book);
            db.SaveChanges();
        }

        public bool Update(Book book)
        {
            db.Entry(book).State = EntityState.Modified;
            db.SaveChanges();
            return true;
        }


        public Book Get(int id)
        {
            return db.Books.Find(id);
        }
    }
}


→有了接口和实现,接下来会用到依赖注入。选择使用Unity,在NuGet中下载。

→首先需要一个依赖注入容器。在项目下创建Helper文件夹,在其中创建IoCContainer类。

using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
using Microsoft.Practices.Unity;

namespace MyMvcAndWebApi.Helper
{
    class ScopeContainer : IDependencyScope
    {
        protected IUnityContainer container;

        public ScopeContainer(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            if (container.IsRegistered(serviceType))
            {
                return container.Resolve(serviceType);
            }
            else
            {
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            if (container.IsRegistered(serviceType))
            {
                return container.ResolveAll(serviceType);
            }
            else
            {
                return new List<object>();
            }
        }

        public void Dispose()
        {
            container.Dispose();
        }
    }

    class IoCContainer : ScopeContainer, IDependencyResolver
    {
        public IoCContainer(IUnityContainer container)
            : base(container)
        {
        }

        public IDependencyScope BeginScope()
        {
            var child = container.CreateChildContainer();
            return new ScopeContainer(child);
        }
    }
}

→在Global.asax中注册Unity。

sing System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using MyMvcAndWebApi.Controllers;
using MyMvcAndWebApi.Helper;
using MyMvcAndWebApi.Models;

namespace MyMvcAndWebApi
{
    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
    // 请访问 http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        //注册控制器,接口和实现
        void ConfigureApi(HttpConfiguration config)
        {
            var unity = new UnityContainer();
            unity.RegisterType<BooksController>();
            unity.RegisterType<IBookRepository, BookRepository>(new HierarchicalLifetimeManager());
            config.DependencyResolver = new IoCContainer(unity);

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            //注册依赖注入
            ConfigureApi(GlobalConfiguration.Configuration);

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}


→创建一个空的Api控制器,编写如下:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MyMvcAndWebApi.Models;

namespace MyMvcAndWebApi.Controllers
{
    public class BooksController : ApiController
    {
        //_repository运行时变量,在首次引用IBookRepository方法时动态分配内存
        private static IBookRepository _repository;

        public BooksController(IBookRepository repository)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }
            _repository = repository;
        }

        //根据惯例,如果action名称以Get开头,那就接收Get请求
        public IEnumerable<Book> GetAllBooks()
        {
            return _repository.GetAll();
        }

        //ASP.NET Web API会自动帮我们把URL中的字符串id转换成参数类型int
        public Book GetBook(int id)
        {
            Book book = _repository.Get(id);
            if (book == null)
            {
                //HttpResponseException封装返回的异常
                //HttpResponseMessage封装返回的信息
                throw new  HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
            return book;
        }

        //添加
        //action名以post开头,按照惯例,接收post请求
        //客户端发送来序列化的Book对象,在服务端对Book对象反序列化
        public HttpResponseMessage PostBook(Book book)
        {
            book = _repository.Add(book);

            // Web API默认返回的状态码为200,可是,根据HTTP/1.1协议,在添加完,我们希望返回201状态码
            var response = Request.CreateResponse(HttpStatusCode.Created, book);

            //返回新创建资源的url
            string uri = Url.Route(null, new {id = book.Id});

            response.Headers.Location = new Uri(Request.RequestUri, uri);
            return response;
        }

        //修改
        //参数id从url中获取,book从request中反序列化
        //根据惯例,Put开头的action,接收put请求
        public void PutBook(int id, Book book)
        {
            book.Id = id;
            if (!_repository.Update(book))
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }

        //删除
        //根据管理,Delete开头接收delete请求
        public HttpResponseMessage DeleteBook(int id)
        {
            _repository.Remove(id);

            //返回200状态码表示删除成功
            //返回202状态码表示正在删除
            //返回204状态码表示没有内容
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
}


以上,所有action方法名称都符合了惯例。

→修改Home/Index.cshtml,我们在此使用jquery与服务端api控制器进行交互。

@section scripts {
    <script src="@Url.Content("~/Scripts/jquery-1.6.2.js")" type="text/javascript"> </script>
    <script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"> </script>
    <script src="@Url.Content("~/Scripts/jQuery.tmpl.js")" type="text/javascript"> </script>
    <script type="text/javascript">
        $(function () {

            //Get请求
            $.getJSON(
                "api/books",
                function (data) {
                    $.each(data,
                        function (index, value) {
                            $("#bookTemplate").tmpl(value).appendTo("#books");
                        }
                    );
                    $("#loader").hide("slow");
                    $("#addBook").show("slow");
                }
            );

            //添加
            $("#addBook").submit(function () {
                $.post(
                    "api/books",
                    $("#addBook").serialize(), //序列化Book对象
                    function (value) {
                        $("#bookTemplate").tmpl(value).appendTo("#books");
                        $("#name").val("");
                        $("#price").val("");
                    },
                    "json"
                );
                return false;
            });

            //删除
            $(".removeBook").live("click", function () {
                $.ajax({
                    type: "DELETE",
                    url: $(this).attr("href"),
                    context: this,
                    success: function () {
                        $(this).closest("li").remove();
                    }
                });
                return false;
            });
            $("input[type=\"submit\"], .removeBook, .viewImage").button();
        });

        //根据id搜索
        function find() {
            var id = $(‘#bookId‘).val();
            $.getJSON("api/books/" + id,
                function (data) {
                    var str = data.Name + ‘: $‘ + data.Price;
                    $(‘#book‘).html(str);
                })
                .fail(
                    function (jqXHR, textStatus, err) {
                        $(‘#book‘).html(‘Error: ‘ + err);
                    });
        }

    </script>
    <script id="bookTemplate" type="text/html">
        <li>
            <p>
                <strong> Book ID:</strong> ${ Id}
                <br />
                <strong> Book Name:</strong> ${ Name }
                <br />
                <strong> Price: $</strong> ${ Price }
            </p>
            <p>
                <a href="${ Self }" class="button small red removeBook">移除</a>
            </p>
        </li>
    </script>
}
<body>
    <form method="post" id="addBook">
    <div class="container_16">
        <h1 class="title-01">Book信息</h1>
    </div>
    <div class="container_16">
        <div class="grid_16 body-container">
            <div class="margin grid_6 alpha">
                <label for="Name">
                    Name</label><br />
                <input type="text" id="name" name="Name" class="text grid_4" />
                <br class="clear" />
                <label for="Price">
                    Price</label><br />
                <input type="text" id="price" name="Price" class="text grid_4" />
                <br class="clear" />
                <input type="submit" value="添加" class="button small green" />
                <br />
                <br />
                <br class="clear" />
                <strong id="book">@*   <label id="book">
                    </label>*@ </strong>
                <br />
                <br class="clear" />
                <br />
                <label for="bookId">
                    根据ID搜索
                </label>
                <br />
                <input type="text" id="bookId" size="20" class="text grid_4" /><br class="clear" />
                <input type="button" value="搜索" onclick="find();" class="button small gray" />
            </div>
            <div class="grid_8 omega">
                <img id="loader" src="images/ajax-loader.gif" />
                <ul id="books" class="books">
                </ul>
            </div>
        </div>
    </div>
    <br class="clear" />
    <div class="footer clearfix">
    </div>
    </form>
</body>


另外,有关Bootsrap的样式在BundleConfig类中定义。

参考资料:http://www.codeproject.com/Articles/344078/ASP-NET-WebAPI-Getting-Started-with-MVC-and-WebAP

时间: 2024-08-04 18:31:59

ASP.NET Web API实践系列02,在MVC4下的一个实例, 包含EF Code First,依赖注入, Bootstrap等的相关文章

ASP.NET Web API实践系列05,消息处理管道

ASP.NET Web API的消息处理管道可以理解为请求到达Controller之前.Controller返回响应之后的处理机制.之所以需要了解消息处理管道,是因为我们可以借助它来实现对请求和响应的自定义处理.所有的请求被封装到HttpRequestMessage这个类中,所有的响应被封装到HttpResponseMessage这个类中. 既然消息处理管道是可扩展的,那么,ASP.NET Web API一定为我们准备了便于扩展的接口或抽象类,它就是HttpMessageHandler抽象类.

ASP.NET Web API实践系列04,通过Route等特性设置路由

ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一文中,体验了通过模版.惯例.HTTP方法来设置路由,这种做法的好处是把路由模版统一放在了App_Start文件夹下的WebApiConfig类中,方便管理,但缺点是不够灵活. REST把一切都看成资源,有时候,一个资源连带子资源,比如Customer和Orders密切关联,我们可能希望输入这样的请求:cust

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

本篇接着上一篇"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 { ge

ASP.NET Web Api 实践系列(一)自我寄宿

从今天开始,研究ASP.NET Web Api(以下有时会简称Web Api).我会写一个实践系列专题,不一定成理论体系,只是遇到问题或心得,记下来.争取用一段较长的时间对ASP.NET Web Api有个较深入的理解.这里我是使用VS2013集成开发环境,如果版本不够,可以用NuGet去下载Web Api相关dll. 今天讨论自我寄宿Web Api. Web Api继承了WCF的优点,除了常规的Web寄宿(IIS)外,还可以在NET的控制台.WinForms等程序中寄宿.这里讲一讲在控制台中寄

ASP.NET Web API实践系列01,以ASP.NET Web Form方式寄宿

创建一个空的ASP.NET Web Form项目. 右键项目,添加新项,创建Web API控制器类,TestController. 删除掉TestController默认的内容,编写如下: using System.Web.Http; namespace WebApplication1 { public class TestController : ApiController { [AcceptVerbs("Get")] public string SayHello() { retur

ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置

ASP.NET Web API的路由和ASP.NET MVC相似,也是把路由放在RouteTable中的.可以在App_Start文件夹中的WebApiConfig.cs中设置路由模版.默认的路由模版是: routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );

ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API

本篇尝试在现有的ASP.NET MVC 4 项目上增加使用ASP.NET Web API. 新建项目,选择"ASP.NET MVC 4 Web应用程序". 选择"基本"项目模版. 在Controllers文件夹下添加一个名称为"TestController"的空API控制器. 在引用文件夹中多了以下程序集:System.Web.HttpSystem.Web.Http.WebHostSystem.Net.HttpSystem.Net.Http.Fo

ASP.NET Web Api 实践系列(二)Get/Post方式调用Web Api

本文给出Get/Post方式访问Web Api的帮助方法,对于Put/Delete方式的调用跟Post调用类似. 一.Web Api调用帮助类 下面给出Web Api调用帮助类的代码: 1 using System; 2 using System.Collections.Generic; 3 using System.Net.Http; 4 using System.Net.Http.Headers; 5 using System.Text; 6 using System.Web; 7 8 na

ASP.NET Web API 记录请求响应数据到日志的一个方法

原文:http://blog.bossma.cn/dotnet/asp-net-web-api-log-request-response/ ASP.NET Web API 记录请求响应数据到日志的一个方法 REST风格的服务架构已经成为越来越多人的选择,之前我用过WCF来实现REST服务,WCF是一个很强大的框架,干这点小事有点太沉重的感觉.后来微软又推出了一个ASP.NET Web API,专门用来处理一些基本的Http服务,即灵活又简单,推荐大家都看看. 今天这篇文章是使用ASP.NET W