使用ASP.NET Web API构建Restful API

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mzl87/article/details/84947623

目录

介绍

这种方法有什么好处?

Restful约定

构建API

测试API

一点困惑:

最佳实践:

数据传输对象(DTO)

Automapper

IHttpActionResult

使用Web API

结论


在本文中,我们将构建测试并使用asp.net web api

介绍

让我们快速回顾一下ASP.NET MVC架构。因此,当请求到达我们的应用程序时,MVC Framework将该请求移交给控制器中的操作,此操作大部分时间返回一个视图,然后由razor视图引擎解析,最终将HTML标记返回给客户端。因此,在这种方法中,在服务器上生成html标记,然后返回到客户端。

https://www.codeproject.com/KB/webservices/1252477/client-server.PNG

有另一种生成HTML标记的方法,我们可以在客户端生成它。因此,不是我们的操作返回HTML标记,它们可以返回原始数据。

https://www.codeproject.com/KB/webservices/1252477/data.PNG

这种方法有什么好处?

在客户端上生成标记有很多好处。

  • 它需要更少的服务器资源(它潜在地提高了应用程序的可伸缩性,因为每个客户机将负责生成自己的视图)
  • 原始数据通常比HTML标记需要更少的带宽。因此,数据可能会更快到达客户端。这可以提高应用程序的感知性能。
  • 此方法支持广泛的客户端,如移动和平板电脑应用程序。

这些应用程序简称为端点获取数据并在本地生成视图。我们将这些端点称为数据服务(Web API),因为它们只返回数据,而不是标记。

Web API不仅限于交叉设备,它还广泛用于我们的Web应用程序中,以添加新功能,如youtubefacebooktwitter等许多热门网站,从而公开我们可以在我们的Web应用程序中使用的公共数据服务。我们可以将他们的数据与我们应用程序中的数据合并,并为新用户提供新的体验。这些都是好处。

这些数据服务不仅仅是为了获取数据,我们还提供修改数据的服务,例如添加客户等。我们用来构建这些数据服务的框架称为Web API。这个框架是在ASP.Net MVC之后开发的,但它遵循ASP.NET MVC的相同体系结构和原理,因此它具有路由,控制器,操作,操作结果等。我们在这里看到的细微差别也很少。在.Net Core中,Microsoft已将这两个框架(ASP.NET MVCASP.NET Web API)合并到一个框架中。

Restful约定

所以你知道什么是http服务,什么是web api。在这里,我们将开发一个支持几种不同类型请求的应用程序。

GET        / api / customers(获取客户列表)

GET       / api / customers / 1(获得单个客户)

POST     / api / customers(添加客户并在请求正文中添加客户数据)

不要混淆请求数据的GETPOST方式,我们使用get请求来获取资源或数据的列表。我们使用post请求来创建新的数据。

现在更新学生我们使用PUT请求。

PUT        / api / customers / 1

因此,客户的ID位于URL中,要更新的实际数据或属性将位于请求正文中。最后删除学生。

Delete     / api / customers / 1

我们将HttpDelete请求发送到端点。所以你在这里看到的,就请求类型和端点而言,是一个标准约定,被交付请求RESTRepresentational State Transfer

构建API

此类派生自ApiController,而不是Controller。如果您正在使用任何现有项目,则只需在controllers文件夹中添加一个新文件夹,并在此处添加api控制器。并添加这些操作,但在apis中定义操作之前,这是我的Customer模型类。

public class Customer
{
    public int Id { get; set; }

    [Required]
    [StringLength(255)]
    public string Name { get; set; }

    public bool IsSubscribedToNewsLetter { get; set; }

    [Display(Name = "Date of Birth")]
    public DateTime? Birthdate { get; set; }

    [Display(Name = "Membership Type")]
    public byte MembershipTypeId { get; set; }

    // it allows us to navigate from 1 type to another
    public MembershipType MembershipType { get; set; }
}

这是我的DbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        :base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    public DbSet<Customer> Customers { get; set; }
    public DbSet<MembershipType> MembershipTypes { get; set; }
}

现在,您可以轻松地为Api编写操作。

public IEnumerable<Customer> GetCustomers()
{
}

因为我们正在返回一个对象列表。按约定,此操作将作出回应

//Get       / api / customers

所以这是ASP.Net Web API中内置的约定。现在,在这个操作中,我们将使用我们的上下文从数据库中获取客户。

namespace MyAPI.Controllers.Api
{
    public class CustomersController : ApiController
    {
        private readonly ApplicationDbContext _context;

        public CustomersController()
        {
            _context = new ApplicationDbContext();
        }

        // GET /api/customers
        public IEnumerable<Customer> GetCustomers()
        {
            return _context.Customers.ToList();
        }
    }
}

如果找不到资源,我们返回找不到httpresponse,否则我们返回该对象。

// POST /api/customers
[HttpPost]
public Customer CreateCustomer(Customer customer)
{
}

所以这是客户参数将在请求体中,ASP.NET Web API框架将自动初始化它。现在我们应该用HttpPost标记这个操作,因为我们正在创建资源。如果我们遵循命名约定,那么我们甚至不需要将操作动词放在操作上。

// POST /api/customers
public Customer PostCustomer(Customer customer)
{
}

但最初它不是那么好的方法,让我们假设您将来重构代码并重命名您的操作,那么您的代码肯定会破坏。所以总是喜欢在操作的顶部使用Http动词。

现在让我们使用api操作的post请求的将客户对象插入到数据库中。

// POST /api/customers
[HttpPost]
public Customer CreateCustomer(Customer customer)
{
    if (!ModelState.IsValid)
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    _context.Customers.Add(customer);
    _context.SaveChanges();

    return customer;
}

另一个操作让我们假设我们要更新记录。

// PUT /api/customers/1
[HttpPut]
public void UpdateCustomer(int id, Customer customer)
{
    if (!ModelState.IsValid)
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);

    // Might be user sends invalid id.
    if (custmr == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    custmr.Birthdate = customer.Birthdate;
    custmr.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;
    custmr.Name = customer.Name;
    custmr.MembershipTypeId = customer.MembershipTypeId;

    _context.SaveChanges();
}

在这种情况下,不同的人有不同的意见来返回void或对象。如果我们进行Api的删除操作。

// Delete /api/customers/1
[HttpDelete]
public void DeleteCustomer(int id)
{
    var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);

    // Might be user sends invalid id.
    if (custmr == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    _context.Customers.Remove(custmr);

    // Now the object is marked as removed in memory
    // Now it is done
    _context.SaveChanges();
}

这就是我们如何使用restful约定来构建api

测试API

如果我们运行应用程序并请求api控制器,我们可以看到基于XML语言的客户列表。

<a href="http://localhost:53212/api/customers">http://localhost:53212/api/customers</a>

https://www.codeproject.com/KB/webservices/1252477/XML.PNG

因此,ASP.NET Web API具有我们所谓的媒体格式化程序。因此,我们从一个动作中返回的内容(在我们的情况下,客户列表将根据客户要求进行格式化)让我解释一下我的意思和我想说的内容。

在上面的屏幕上检查浏览器并刷新页面,在这里您将看到客户请求。

https://www.codeproject.com/KB/webservices/1252477/response.PNG

这里查看内容类型,如果您在我们的请求中没有设置内容类型标头,则默认情况下服务器采用application / xml

注意: General是请求标头,Response Headers是我们的响应标头。正如您在Request Header中看到的,我们没有任何内容类型。现在让我告诉你最好测试api的方式并返回json数据。

在您的计算机中安装Postman Desktop App。并使用localhost端口号复制浏览器链接并将其粘贴到postman

在这里,我们将请求的urllocalhost放在一起,而响应在json中返回。

https://www.codeproject.com/KB/webservices/1252477/json.PNG

如果我们点击Header选项卡,这里我们将看到我们的请求标头内容类型是application / json

https://www.codeproject.com/KB/webservices/1252477/app-json.PNG

大多数时候我们将使用json,因为它是javascript代码的原生代码,比xml快得多。XML媒体格式主要用于政府等大型组织,因为它们落后于现代技术。Json格式更轻量级,因为它没有像xml那样的多余的开启和关闭选项卡。

一点困惑:

有时当你使用Apipostman时,大多数人都会对Postman的界面感到困惑,因为他们之前从未使用过postman。记住这一点非常简单,

https://www.codeproject.com/KB/webservices/1252477/req_resp.PNG

因此,如果您正在处理请求并尝试更改请求的某些信息,请关注请求标头,如果您正在监视响应,请在响应标头中查看结果。因为它们看起来相同,有时当请求标题的向下滚动消失时。所以不要混淆事情。

现在让我们使用Api Post 操作在数据库中插入一个客户。

https://www.codeproject.com/KB/webservices/1252477/post.PNG

从下拉列表和请求正文选项卡中选择Post请求。您可以在单击表单数据时插入具有键值对的客户。但大多数时候我们使用json格式。所以点击raw并在这里写json

https://www.codeproject.com/KB/webservices/1252477/raw.PNG

不要将Id属性放在json中,因为当我们在数据库中插入数据时,它是硬性规则,在服务器上自动生成id

现在点击Send按钮,这里我已通过Post api操作成功插入数据并获得响应。

https://www.codeproject.com/KB/webservices/1252477/created.PNG

这里上面的块是请求块,下面的块是响应块。你可能会在这里遇到某种错误。

https://www.codeproject.com/KB/webservices/1252477/error.PNG

如果您阅读错误消息'此资源不支持请求实体的媒体类型'text / plain'。这是错误消息。

现在来解决这个错误。单击Header选项卡并添加content-type的值('application / json'

https://www.codeproject.com/KB/webservices/1252477/Solution.PNG

这里已经添加了值。查看请求的状态代码是200 OK,我们可以在下面看到响应正文。

现在让我们更新客户实体。

https://www.codeproject.com/KB/webservices/1252477/HttpPut.PNG

看看它已经更新。

https://www.codeproject.com/KB/webservices/1252477/Put_Response.PNG

现在让我们删除一条记录,只需在下拉列表中选择Delete,然后在url中指定带正斜杠的id,然后单击Send按钮。它会被自动删除。

最佳实践:

最佳实践是在构建api时以及在应用程序中使用api之前。通过Postman测试api会更好。

数据传输对象(DTO

所以现在我们已经构建了这个API,但这个设计存在一些问题。我们的api接收或返回Customer对象。现在你可能会想到这种方法有什么问题?实际上,Customer对象是我们应用程序的域模型的一部分。当我们在应用程序中实现新功能时,它被认为是可以经常更改的实现细节,并且这些更改可能会抓取依赖于客户对象的现有客户端,即如果我们重命名或删除我们的属性,这会影响依赖于属性的客户端。所以基本上我们使api的协议尽可能稳定。在这里我们使用DTO

DTO是普通数据结构,用于从服务器上的客户端传输数据,反之亦然,这就是我们称之为数据传输对象的原因。通过创建DTO,我们在重构域模型时减少了对API破坏的可能性。当然,我们应该记住,改变这些DTO可能会产生高昂成本。所以最重要的是我们的api不应该接收或返回Customer模型类对象。

API中使用域对象的另一个问题是我们在应用程序中打开了安全漏洞。黑客可以轻松地在json中传递其他数据,并将它们映射到我们的域对象。如果不应该更新其中一个属性,黑客可以轻易绕过这个,但如果我们使用DTO,我们可以简单地排除可以更新的属性。因此,在项目中添加名为DTO的新文件夹并添加CustomerDTO类,并将Customer域模型类的所有属性及其数据注释属性复制并粘贴到CustomerDTO中。现在从CustomerDTO中删除导航属性,因为它正在创建与MembershipType域模型类的依赖关系。

namespace MyAPI.DTOs
{
    public class CustomerDTO
    {
        public int Id { get; set; }

        [Required]
        [StringLength(255)]

        public string Name { get; set; }

        public bool IsSubscribedToNewsLetter { get; set; }

        public DateTime? Birthdate { get; set; }

        public byte MembershipTypeId { get; set; }
    }
}

接下来我们要在我们的api中使用CustomerDTO而不是Customer域类对象。因此,为了减少大量代码逐个绑定属性,我们使用Automapper

Automapper

Package Manager控制台安装automapper包。

PM > Install-Package Automapper -version:4.1

现在在App_StartMappingProfile.cs)中添加新类并继承Profile

using AutoMapper;

namespace MyAPI.App_Start
{
    public class MappingProfile : Profile
    {

    }
}

现在创建构造函数并在两种类型之间添加映射配置。

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        Mapper.CreateMap<Customer, CustomerDTO>();
        Mapper.CreateMap<CustomerDTO, Customer>();
    }
}

CreateMap的第一个参数是Source(源对象),第二个参数是destination(目标对象)。当我们使用CreateMap方法时,automapper会自动使用反射来扫描这些类型。它找到它们的属性并根据它们的名称对它们进行映射。这就是我们调用automapper(基于约定的映射工具)的原因,因为它使用属性名作为映射对象的约定。所以这里是映射配置文件,现在我们需要在应用程序启动时加载它。

现在打开Global.asax.cs文件并编写Application_Start()的代码

protected void Application_Start()
{
    Mapper.Initialize(c => c.AddProfile<MappingProfile>());
    GlobalConfiguration.Configure(WebApiConfig.Register);
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

现在打开ApiCustomerController。让我们从这里开始改变。

// GET /api/customers
public IEnumerable<CustomerDTO> GetCustomers()
{
    return _context.Customers.ToList();
}

现在我们要返回CustomerDTO类型而不是Customer对象。现在我们需要将此Customer对象映射到CustomerDTO所以我们使用linq扩展方法。

// GET /api/customers
public IEnumerable<CustomerDTO> GetCustomers()
{
    return _context.Customers.ToList()
       .Select(Mapper.Map<Customer, CustomerDTO>);
}

Mapper.Map <CustomerCustomerDTO>

这个代表进行映射。我们可以看到我们没有放置函数调用小括号,因为我们没有在这里调用函数。我们在这里引用它。映射函数在执行时自动调用。

// GET /api/customers/1
public Customer GetCustomer(int id)
{
    var customer = _context.Customers.SingleOrDefault(x => x.Id == id);

    // This is part of the RESTful Convention
    if (customer == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return customer;
}

在这个函数中,因为我们返回一个对象所以我们不使用Select扩展方法。这里我们直接使用mapper

// GET /api/customers/1
public CustomerDTO GetCustomer(int id)
{
    var customer = _context.Customers.SingleOrDefault(x => x.Id == id);

    // This is part of the RESTful Convention
    if (customer == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    return Mapper.Map<Customer, CustomerDTO>(customer);
}

现在进行下一个CreateCustomer操作,

// POST /api/customers
[HttpPost]
public CustomerDTO CreateCustomer(CustomerDTO customerDto)
{
    if (!ModelState.IsValid)
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);
    _context.Customers.Add(customer);
    _context.SaveChanges();

    // Here we make our CustomerDto completely fill, because after
    // adding customer to Customer table (id is assigned to it)
    // & Now we assigned this id to customerDto
    customerDto.Id = customer.Id;
    return customerDto;
}

这就是我们如何使用DtoAutomapper

现在让我们更新UpdateCustomer动作api方法。

// PUT /api/customers/1
[HttpPut]
public void UpdateCustomer(int id, CustomerDTO customerDto)
{
    if (!ModelState.IsValid)
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);

    // Might be user sends invalid id.
    if (custmr == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    Mapper.Map<CustomerDTO, Customer>(customerDto, custmr);
    //custmr.Birthdate = customerDto.Birthdate;
    //custmr.IsSubscribedToNewsLetter = customerDto.IsSubscribedToNewsLetter;
    //custmr.Name = customerDto.Name;
    //custmr.MembershipTypeId = customerDto.MembershipTypeId;
    _context.SaveChanges();
}

这就是我们使用Automapper映射对象的方式。现在,automapper有一些在某些情况下可能会发现有用的功能,即如果您的属性名称不匹配,您可以覆盖默认约定,或者您可以从映射中排除某些属性,或者您可能想要创建自定义映射类。如果您想了解更多信息,可以从Automapper文档中学习。

IHttpActionResult

好吧看看这个CreateCustomer操作方法

// POST /api/customers
[HttpPost]
public CustomerDTO CreateCustomer(CustomerDTO customerDto)
{
    if (!ModelState.IsValid)
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);
    _context.Customers.Add(customer);
    _context.SaveChanges();

    // Here we make our CustomerDto completely fill, because after
    // adding customerDto to Customer table (id is assigned to it)
    // & Now we assigned this id to customerDto
    customerDto.Id = customer.Id;

    return customerDto;
}

在这里,我们只是返回CustomerDto,最终会产生这样的响应

https://www.codeproject.com/KB/webservices/1252477/200.PNG

但是在restful约定中当我们创建资源时,状态代码应为201created所以我们需要更多地控制操作的响应返回并实现这一点,而不是返回CustomerDto,我们返回IHttpActionResult这个接口类似于我们在MVC框架中的ActionResult所以它由几个不同的类实现,这里在ApiController中,我们有很多方法来创建一个实现IHttpActionResult接口的类的实例。

现在,如果模型无效而不是抛出异常,请使用辅助方法BadRequest()

// POST /api/customers
[HttpPost]
public IHttpActionResult CreateCustomer(CustomerDTO customerDto)
{
    if (!ModelState.IsValid)
    {
        return BadRequest();
    }

    var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);
    _context.Customers.Add(customer);
    _context.SaveChanges();

    // Here we make our CustomerDto completely fill, because after
    // adding customerDto to Customer table (id is assigned to it)
    // & Now we assigned this id to customerDto
    customerDto.Id = customer.Id;
    return Created(new Uri(Request.RequestUri + "/" + customer.Id),
        customerDto);
}

我们可以看到如果ModelState是无效的,它返回BadRequest,如果已经添加了customer,那么我们在Created()中使用我们最终创建新对象的对象返回具有此资源IDUri 

https://www.codeproject.com/KB/webservices/1252477/201.PNG

看这里我们创建了另一个资源,现在状态为201 Created如果我们查看位置选项卡

https://www.codeproject.com/KB/webservices/1252477/location.PNG

这就是新创造的客户的uri。这是restful约定的一部分。所以在Web Api中,我们更倾向于使用IHttpActionResult作为操作的返回类型。

现在让我们对此Web Api中的其余操作进行更改。这是我们的Api的完整代码

public class CustomersController : ApiController
{
    private readonly ApplicationDbContext _context;

    public CustomersController()
    {
        _context = new ApplicationDbContext();
    }

    // GET /api/customers
    public IHttpActionResult GetCustomers()
    {
        return Ok(_context.Customers.ToList()
            .Select(Mapper.Map<Customer, CustomerDTO>));
    }

    // GET /api/customers/1
    public IHttpActionResult GetCustomer(int id)
    {
        var customer = _context.Customers.SingleOrDefault(x => x.Id == id);

        // This is part of the RESTful Convention
        if (customer == null)
        {
            return NotFound();
        }

        return Ok(Mapper.Map<Customer, CustomerDTO>(customer));
    }

    // POST /api/customers
    [HttpPost]
    public IHttpActionResult CreateCustomer(CustomerDTO customerDto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);
        _context.Customers.Add(customer);
        _context.SaveChanges();
        // Here we make our CustomerDto completely fill, because after
        // adding customerDto to Customer table (id is assigned to it)
        // & Now we assigned this id to customerDto
        customerDto.Id = customer.Id;

        return Created(new Uri(Request.RequestUri + "/" + customer.Id),
            customerDto);
    }   

    // PUT /api/customers/1
    [HttpPut]
    public IHttpActionResult UpdateCustomer(int id, CustomerDTO customerDto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);

        // Might be user sends invalid id.
        if (custmr == null)
        {
            return NotFound();
        }

        Mapper.Map<customerdto, customer="">(customerDto, custmr);
        _context.SaveChanges();
        return Ok(custmr);
    }
   
    // Delete /api/customers/1
    [HttpDelete]
    public IHttpActionResult DeleteCustomer(int id)
    {
        var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);

        // Might be user sends invalid id.
        if (custmr == null)
        {
            return NotFound();
        }

        _context.Customers.Remove(custmr);
        // Now the object is marked as removed in memory
        // Now it is done
        _context.SaveChanges();
        return Ok(custmr);
    }

}</customerdto,>

我在这里提一下这一点,因为你可以看到我们在UpdateCustomer中有2个参数。如果参数是原始类型,就像我们是int id那样我们将把这个参数放在路由url或查询字符串中。如果我们想要像我们这样初始化我们的复杂类型我们有CustomerDTO,那么我们将始终从postman中的请求体初始化它。所以不要在这里困扰这件事。

现在让我们通过post更新和删除json对象。如果您专注于UpdateCustomer操作参数,这里我们有第一个参数是记录ID,第二个参数是Customer领域模型类对象。

看它在请求头中使用Id,因为我们的实体在这里完成了。

https://www.codeproject.com/KB/webservices/1252477/working.PNG

但是如果我们不在请求标头中提供id,我们将得到错误。

https://www.codeproject.com/KB/webservices/1252477/Put_error.PNG

exceptionMessage属性'Id'是对象的关键信息的一部分,无法修改。实际上这个异常发生在这一行,

Mapper.Map<CustomerDTO, Customer>(customerDto, custmr);

因为customerDto不包含Id,但custmrCustomer模型类的对象变量)具有Id属性。在这里,我们需要告诉Automapper在映射从customerDtocustmr时忽略Id。所以,来看映射配置文件

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        Mapper.CreateMap<Customer, CustomerDTO>();
        Mapper.CreateMap<CustomerDTO, Customer>()
            .ForMember(c => c.Id, opt => opt.Ignore());
    }
}

看它现在正在工作,

https://www.codeproject.com/KB/webservices/1252477/created.PNG

使用Web API

经过适当的api测试后,现在是使用api的时候了。最重要的是我想在这里提一下。现在我们的api准备好了,你可以在任何客户端使用这个api。在这里,我们向您展示使用Visual Studio应用程序进行使用的示例。如果你用我们构建这个api,那么你可以在jquery ajax的帮助下在phppython,任何框架应用程序中使用它。现在我们将使用jquery来调用我们的api。看这个屏幕,这里我展示了一些客户。

https://www.codeproject.com/KB/webservices/1252477/view.PNG

现在我们想要的是单击删除按钮删除行。因此,如果您了解我们如何在屏幕上呈现记录项,显然使用foreach循环。所以在删除锚点标签上点击我们还要记录id以将此id传递给web api删除操作并在成功时删除该行。

@foreach (var customer in Model)
{
    <tr>
        <td>@Html.ActionLink(customer.Name, "Edit", "Customers", new { id = customer.Id }, null)</td>
        @if (customer.Birthdate != null)
        {
            <td>
                @customer.Birthdate
            </td>
        }
        else
        {
            <td>Not Available</td>
        }
        <td>
            <button data-customer-id="@customer.Id" class="btn btn-link js-delete">Delete</button>
        </td>
    </tr>
}

这是html。现在我想通过ajax调用我的api

@section scripts{
    <script>
        $(document).ready(function() {
            $('#customers .js-delete').on('click',
                function () {
                    var button = $(this);
                    if (confirm('Are you sure you want to delete this client?')) {
                        $.ajax({
                            url: '/api/customers/' + button.attr('data-customer-id'),
                            method: 'DELETE',
                            success: function() {
                                button.parents('tr').remove();
                            }
                        })
                    }
                });
        });
    </script>
}

这就是我们使用ajaxapi的方式。现在你可能在想这里我只是将id传递给客户api并定位Delete操作,在 success事件中我直接删除了行。您可能会以不同的方式思考这种情况,因为每个开发人员都有自己的品味。

您可能会想到,首先我们使用Delete方法删除记录,然后从Web ApiGetCustomers()方法获取所有记录,然后通过jquery的每个循环渲染所有这些项。但这种情况需要花费太多时间和效率。当我点击删除锚标签并在检查浏览器中显示结果时,状态为200 ok。这意味着一切正常,我们的代码(删除操作)正如我们所期望的那样工作。因此,我们不需要再次验证数据库中有多少项并通过每个循环呈现它们。

只需简化您的情况,并像我一样删除记录。

结论

因此,结论是当您使用Web Api时,始终遵循Restful约定。Web Api比基于SOAPWeb服务更加的轻量级。他们是跨平台的。Restful Http动词有助于在应用程序中插入,删除,更新,获取记录。在这里,我们看到我们如何使用postman,并有2个不同的窗格,如请求标头和响应标头。大多数时候,开发人员对如何使用jquery ajax使用Web Api操作感到困惑。在这里我们也使用了这个动作。

 

原文地址:https://www.codeproject.com/Articles/1252477/Building-a-Restful-API-With-ASP-NET-Web-API

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/84947623