文档章节

Web Api 简单例子(WebApi+MongoDB+Knockoutjs)

o
 osc_fmg49rzg
发布于 2019/03/20 10:51
字数 1386
阅读 17
收藏 0

精选30+云产品,助力企业轻松上云!>>>

本文很多内容来自 链接

Napoléon本身已经写得很好了,但是出于对该内容学习的要求,自己还是重新做了一遍。

有一些新的东西,不过大多数都是他的,希望大家了解

 

1.引言

最近在找工作,然后就遇到了需要做前后端分离项目的公司,可惜因为自己没做过Web Api项目,因此没通过,今天就特地找文章来学习他。

对于前后端分离的项目来说,Web Api只是提供和数据库操作的功能,可以提供该功能的框架还有MVC和WCP,在这里将Web Api和他的2兄弟比较一下,加深理解

1.1 与MVC

我最开始以为Web Api就是没有返回视图的MVC,其实这样的想法是错误的;

1)首先Web Api是不能返回视图的,MVC可以

2)Web Api是通过Http动词来判断不同的操作(Post,Get,Put,Delete),MVC是通过路由中的Action名来判断不同操作。(更复杂的操作可以通过传参的不同来判断)

 

1.2 与Wcf

都是提供远程接口调用,但是两者都很大的不同

1)Wcf是使用SOAP协议,而Web Api是使用Http协议

2)Wcf一般传输数据的格式是xml,而Web Api一般是使用Json

 

2.Demo例子

这里使用的是MongoDB+Web Api+Knockoutjs

简单介绍一下另两个框架:

MongoDB是NoSql非关系型数据库,轻量级,而且数据基本上都放在内存访问,因此速度快,但是没有事务是硬伤,因此只能存储原子性的数据。

Knockoutjs是一个前端框架,使用的是MVVM的模式,数据绑定(就这方面来说Vue和他很像),也就是数据的改变会自动同步到Dom上。

功能很简单,就是对Contact的增删改查

2.1 安装MongoDB数据库和NosqlBooster for MongoDB(MongoDB的图形化处理程序)

2.2 VS2017新建一个Web Api项目

2.2.1 在Nuget中添加上对应的框架,如图

后者是MongoDB的驱动包。

2.2.2 在Models文件夹中添加Contact实体类,和对应的仓库

public class Contact
{
    [BsonId]
    public string Id { get; set; }
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
    public DateTime LastModified { get; set; }
}

public interface IContactRepository
{
    IEnumerable<Contact> GetAllContacts();
    Contact GetContact(string id);
    Contact AddContact(Contact item);
    bool RemoveContact(string id);
    bool UpdateContact(string id, Contact item);
}

public class ContactRepository : IContactRepository
{
    MongoClient _server = null;
    IMongoDatabase _database = null;
    IMongoCollection<Contact> _contacts = null;

    public ContactRepository(string connection)
    {
        if (string.IsNullOrWhiteSpace(connection))
        {
            connection = "mongodb://localhost:27017";
        }

        _server = new MongoClient(connection);
        _database = _server.GetDatabase("Contacts");
        _contacts = _database.GetCollection<Contact>("contacts");

        // Reset database and add some default entries
        var filter = Builders<Contact>.Filter.Where(a => 1 == 1);
        _contacts.DeleteMany(filter);
        for (int index = 1; index < 5; index++)
        {
            Contact contact1 = new Contact
            {
                Email = string.Format("test{0}@example.com", index),
                Name = string.Format("test{0}", index),
                Phone = string.Format("{0}{0}{0} {0}{0}{0} {0}{0}{0}{0}", index)
            };
            AddContact(contact1);
        }
    }

    public IEnumerable<Contact> GetAllContacts()
    {
        return _contacts.Find(a => 1 == 1).ToList();
    }

    public Contact GetContact(string id)
    {
        //IMongoQuery query = Query.EQ("_id", id);
        return _contacts.Find(a => a.Id == id).FirstOrDefault();
    }

    public Contact AddContact(Contact item)
    {
        item.Id = Guid.NewGuid().ToString();
        item.LastModified = DateTime.UtcNow;
        _contacts.InsertOne(item);
        return item;
    }

    public bool RemoveContact(string id)
    {
        var filter = Builders<Contact>.Filter.Where(a => a.Id == id);
        var result = _contacts.DeleteOne(filter);
        return result.DeletedCount == 1;
    }

    public bool UpdateContact(string id, Contact item)
    {
        var query = Builders<Contact>.Filter.Where(a => a.Id == id);
        item.LastModified = DateTime.UtcNow;
        var update = Builders<Contact>.Update
            .Set("Email", item.Email)
            .Set("LastModified", DateTime.UtcNow)
            .Set("Name", item.Name)
            .Set("Phone", item.Phone);
        var result = _contacts.UpdateOne(query, update);
        return result.ModifiedCount > 0;
    }
}

 2.2.3 在Controllers文件夹中添加对应的ContactsController如下

public class ContactsController : ApiController
{
    private static readonly IContactRepository _contacts = new ContactRepository(string.Empty);

    public IQueryable Get()
        {
            return _contacts.GetAllContacts().AsQueryable();
        }

    public Contact Get(string id)
        {
            Contact contact = _contacts.GetContact(id);
            if (contact == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            return contact;
        }

    public Contact Post(Contact value)
        {
            Contact contact = _contacts.AddContact(value);
            return contact;
        }

    public void Put(string id, Contact value)
        {
            if (!_contacts.UpdateContact(id, value))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

    public void Delete(string id)
        {
            if (!_contacts.RemoveContact(id))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }
}

2.2.4 在HomeController中添加要调用该Api的控制器和对应的页面

public ActionResult Admin()
{
    string apiUri = Url.HttpRouteUrl("DefaultApi", new { controller = "contacts", });
    ViewBag.ApiUrl = new Uri(Request.Url, apiUri).AbsoluteUri.ToString();

    return View();
}

/Views/Home/Admin.cshtml

@model WebApplication1.Models.Contact

@{
    ViewBag.Title = "Admin";
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript" src="@Url.Content("~/Scripts/knockout-3.5.0.js")"></script>
    <script type="text/javascript">
      function ProductsViewModel() {
          var self = this;
          self.products = ko.observableArray();

          var baseUri = '@ViewBag.ApiUrl';

          self.create = function (formElement) {
              // If valid, post the serialized form data to the web api
              $(formElement).validate();
              if ($(formElement).valid()) {
                  $.post(baseUri, $(formElement).serialize(), null, "json")
                      .done(function (o) { self.products.push(o); });
              }
          }

          self.update = function (product) {
              $.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
          }

          self.remove = function (product) {
              // First remove from the server, then from the UI
              $.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
                  .done(function () { self.products.remove(product); });
          }

          $.getJSON(baseUri, self.products);
      }

      $(document).ready(function () {
          ko.applyBindings(new ProductsViewModel());
      })
    </script>
}

<h2>Admin</h2>
<div class="content">
    <div class="float-left">
        <ul id="update-products" data-bind="foreach: products">

            <li>
                <div>
                    <div class="item">ID</div> <span data-bind="text: $data.Id"></span>
                </div>
                <div>
                    <div class="item">Name</div>
                    <input type="text" data-bind="value: $data.Name" />
                </div>
                <div>
                    <div class="item">Phone</div>
                    <input type="text" data-bind="value: $data.Phone" />
                </div>
                <div>
                    <div class="item">Email</div>
                    <input type="text" data-bind="value: $data.Email" />
                </div>
                <div>
                    <div class="item">Last Modified</div> <span data-bind="text: $data.LastModified"></span>
                </div>
                <div>
                    <input type="button" value="Update" data-bind="click: $root.update" />
                    <input type="button" value="Delete Item" data-bind="click: $root.remove" />
                </div>
            </li>
        </ul>
    </div>

    <div class="float-right">
        <h2>Add New Product</h2>
        <form id="addProduct" data-bind="submit: create">
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>Contact</legend>
                @Html.EditorForModel()
                <p>
                    <input type="submit" value="Save" />
                </p>
            </fieldset>
        </form>
    </div>
</div>
View Code

2.2.5 最后重新编译后,就可以查看了

3.总结

其实用这个代码来体会MongoDB,Web Api和MVVM都挺不错的,感谢原作者

大家通过这个代码可以看到控制器中只有几个方法,Ajax调用的类型不一样,程序就会进入不同的方法,相信这是在做框架的时候微软作出的约定。如图

 

就好像MVC是通过路由去通过反射获取要执行的action方法一样,这里应该是在获取header类型的前提下通过反射获取对应的action名。

而且Api直接就会将对象数据转化成Json,不需要使用MVC那样的JsonResult

最后代码放在这里供大家学习  下载

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
React Native转web方案:react-native-web

原文地址:github.com/HuJiaoHJ/bl… React源码 React16源码之React Fiber架构 从源码看React异常处理 从源码看React.PureComponent 实践总结 web移动端布局的那些事儿 React Native转web方案...

大灰狼的小绵羊哥哥
2018/11/13
0
0
react native转web方案:react-native-web

本文将从三个方面分享 react native 转 web 方案:react-native-web react-native-web 的使用 react-native-web 源码分析 react-native-web 实践 react-native-web:github.com/necolas/rea…......

hujiao
2018/08/20
0
0
数百个 HTML5 例子学习 HT 图形组件 – 3D 建模篇

http://www.hightopo.com/demo/pipeline/index.html 《数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇》里提到 HT 很多情况下不需要借助 3Ds Max 和 Blender 等专业 3D 建模工具也能做出...

xhload3d
2016/09/30
565
0
简易实现一个express

写在前面 Express是一个简洁、灵活的node.js Web应用开发框架,它提供一系列强大的特性,帮助你创建各种web和移动应用。丰富的HTTP快捷方法和任意排列组合的Connect中间件,让你创建健壮、友...

慕晨同学
2018/12/28
0
0
Web Animation Api 入门

Web Animation Api 入门 在网页中使用动画提供了更好的用户体验,例如抽屉式菜单。 目前为止,web动画可以通过css3 transitions,css

cnTomato
2019/09/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

LINUX_VERSION_CODE与KERNEL_VERSION

由于Linux版本的在不断更新,当设备驱动去兼容不同版本的内核时,需要知道当前使用的内核源码版本,以此来调用对应版本的内核API,这两个宏定义在文件 /usr/include/linux/version.h#defin...

osc_5g68egoj
13分钟前
16
0
JVM09-类加载过程

这一篇我们来学习一下JVM中的类加载过程。说到类的加载过程,我们需要先了解一下JVM中类的生命周期。在JVM中类的生命周期有七个阶段。分别是: 加载(Loading):加载是通过类加载器从不同的...

osc_zai0dt9q
14分钟前
17
0
###豪豪豪豪######2020 推荐系统技术演进趋势了解

读知乎文章《推荐系统技术演进趋势:从召回到排序再到重排》笔记: 《推荐系统技术演进趋势:从召回到排序再到重排》这篇文章主要说了下最近两年,推荐系统技术的一些比较明显的技术发展趋势...

osc_lhmderwy
15分钟前
9
0
SpringBoot入门实现RESTFUL API以及用Postman测试

Model @Data@Builderpublic class Article { private Long id; private String author; private String title; private String content; private Date createTime;}......

osc_7ludm6s2
16分钟前
4
0
Leetcode 83 删除排序链表中的重复元素-链表双指针

维护两个指针,第一个指针指向链表没有重复元素的最后一个位置,第二个指针向后扫描,直到末尾。严格来说,在C++中需要手动释放内存。但在算法题或者Java中不需要这么做。 class Solution {...

osc_n1x6m26g
18分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部