推荐ServiceStack API结构 [英] Recommended ServiceStack API Structure

查看:98
本文介绍了推荐ServiceStack API结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图研究出最好的方法来组织我们的API;我们评论,我们在一个标准的REST架构已经设置(列表中的一个所有,列表,创建,更新等)。它并不完全适合的例子是:每次审查都可以链接到一个或多个其他类型的如事件,地点或事物。

I'm trying work out the best way to structure our API; we have Reviews which we've setup in a standard REST structure (list one, list all, create, update etc). Where it doesn't quite fit the examples is: each review can be linked to one or more other types e.g. Event, Location or Thing.

我的想法是对的URL会沿着线:
/事件/评论/(或此相反例如/评论/事件/)
/位置/评论/
/事/评论/

My thinking is the urls would be along the lines of: /event/reviews/ (or the reverse of this e.g. /reviews/event/) /location/reviews/ /thing/reviews/

不过,我可以看到的问题是GET对于这些应该返回父对象,即一个事件。

The issue I can see however is the "GET" for each of these should return the parent object i.e. an Event.

因此​​,使用ServiceStack,什么是处理这种情况的最好方法?难道要为每个数据请求的定制服务,而不是滥用外的现成的REST设置或有我错过了什么更根本的?

So using ServiceStack, what's the best way to handle this scenario? Is it to create a custom service for each data request rather than abusing the out-of-the-box REST setup or have I missed something more fundamental?

推荐答案

一是最佳的解决方案是一个相当主观的词。我一般会瞄准干燥,促进最不费力,摩擦和繁琐重复使用,高性能的解决方案,而其他人可能在它遵循REST的原则如何界定密切最佳。所以,你会得到不同的反应取决于目标是什么。我只能提供我会怎么对待它。

Firstly "Best" solution is a fairly subjective term. I'll generally aim for DRY, re-usable, performant solutions that promotes the least effort, friction and chattiness, whilst others may define "Best" in how closely it follows the principles of REST. So you will get varied responses depending on what the goals are. I can only offer how I would approach it.

有一点要记住的是你如何定义和ServiceStack设计你的业务的公平去耦你如何揭露他们,因为你可以在任何自定义路由下暴露你的服务。 ServiceStack鼓励基于消息的设计,所以你应该给每个操作一个截然不同的消息。

One thing to keep in mind is how you define and design your services in ServiceStack are fairly de-coupled in how you expose them, since you can expose your services under any custom route. ServiceStack encourages a message-based design so you should give each operation a distinct message.

我会使用一个逻辑URL结构,我的目标是重新present一个名词,它是分层结构的标识符,即父路径归类你的资源,并赋予它意义的上下文。因此,在这种情况下,如果你想揭露事件及评论我的倾向是去以下网址结构:

I'd use a logical Url structure that I aim to represent the identifier of a noun, which is hierarchically structured, i.e. the parent path categorizes your resource and gives it meaningful context. So in this case if you wanted to expose Events and reviews my inclination is to go with following url structure:

/events             //all events
/events/1           //event #1
/events/1/reviews   //event #1 reviews

每个这些资源标识符可以有任何HTTP动词适用于他们。

Each of these resource identifiers can have any HTTP Verb applied to them

有关实施我一般遵循基于消息的设计和组基于响应类型的所有相关业务和呼叫上下文。为此,我会做一些这样的:

For the implementation I generally follow a message-based design and group all related operations based on Response type and call context. For this I would do something like:

[Route("/events", "GET")]
[Route("/events/category/{Category}", "GET")] //*Optional top-level views
public class SearchEvents : IReturn<SearchEventsResponse>
{
   //Optional resultset filters, e.g. ?Category=Tech&Query=servicestack
   public string Category { get; set; } 
   public string Query { get; set; }
}

[Route("/events", "POST")]
public class CreateEvent : IReturn<Event>
{
   public string Name { get; set; }
   public DateTime StartDate { get; set; }
}

[Route("/events/{Id}", "GET")]
[Route("/events/code/{EventCode}", "GET")] //*Optional
public class GetEvent : IReturn<Event>
{
   public int Id { get; set; }
   public string EventCode { get; set; } //Alternative way to fetch an Event
}

[Route("/events/{Id}", "PUT")]
public class UpdateEvent : IReturn<Event>
{
   public int Id { get; set; }
   public string Name { get; set; }
   public DateTime StartDate { get; set; }
}

,并按照事件的评论类似的模式

And follow a similar pattern for Event reviews

[Route("/events/{EventId}/reviews", "GET")]
public class GetEventReviews : IReturn<GetEventReviewsResponse>
{
   public int EventId { get; set; }
}

[Route("/events/{EventId}/reviews/{Id}", "GET")]
public class GetEventReview : IReturn<EventReview>
{
   public int EventId { get; set; }
   public int Id { get; set; }
}

[Route("/events/{EventId}/reviews", "POST")]
public class CreateEventReview : IReturn<EventReview>
{
   public int EventId { get; set; }
   public string Comments { get; set; }
}

的实施应相当直截了当根据这些消息,这(取决于code碱基大小)我会安排在2 EventsService EventReviewsService 班。我要指出,我用多元化的服务请求DTO自己的名字,以避免与同名的数据模型冲突。

The implementation should be fairly straight forward based on these messages, which (depending on code-base size) I would organize in 2 EventsService and EventReviewsService classes. I should note that I use pluralization for Service Request DTO names myself to avoid clashing with data models of the same name.

虽然我已经分开 UpdateEvent CreateEvent 在这里,我有时会将它们合并成一个单一的幂等 StoreEvent 运行,如果用例证。

Although I've separated UpdateEvent and CreateEvent here, I will sometimes will merge them into a single idempotent StoreEvent operation if the use-case permits.

理想的根级别的 APPHOST 的项目应保持轻量和自由实现的。虽然只有少数的服务小项目它的确定对什么事都可以在一个单一的项目,并在需要时简单地增加你的架构。

Ideally the root-level AppHost project should be kept lightweight and implementation-free. Although for small projects with only a few services it's ok for everything to be in a single project and to simply grow your architecture when and as needed.

有关中型到大型项目,我们建议的物理结构低于这个例子的目的,我们将假设我们的应用程序名为 EventMan

For medium-to-large projects we recommend the physical structure below which for the purposes of this example we'll assume our Application is called EventMan.

项目的顺序也显示它的依赖,例如顶级 EventMan 项目引用全部子项目,而最后的 EventMan.ServiceModel 项目引用的

The order of the projects also show its dependencies, e.g. the top-level EventMan project references all sub projects whilst the last EventMan.ServiceModel project references none:

- EventMan
    AppHost.cs              // ServiceStack ASP.NET Web or Console Host Project

- EventMan.ServiceInterface // Service implementations (akin to MVC Controllers)
    EventsService.cs
    EventsReviewsService.cs

- EventMan.Logic            //For larger projs: pure C# logic, data models, etc
    IGoogleCalendarGateway  //E.g of a external dependency this project could use

- EventMan.ServiceModel     //Service Request/Response DTOs and DTO types
    Events.cs               //SearchEvents, CreateEvent, GetEvent DTOs 
    EventReviews.cs         //GetEventReviews, CreateEventReview
    Types/
      Event.cs              //Event type
      EventReview.cs        //EventReview type

随着 EventMan.ServiceModel DTO的存放在自己单独的实施和自由依赖的DLL,你可以自由地在任何.NET客户端项目分享这个DLL作为-is - 你可以使用任何通用 C#服务客户端的使用以提供一个死对终端类型的API,没有任何code根。

With the EventMan.ServiceModel DTO's kept in their own separate implementation and dependency-free dll, you're freely able to share this dll in any .NET client project as-is - which you can use with any of the generic C# Service Clients to provide an end-to-end typed API without any code-gen.

借助简单的客户REST示例有创建一个简单的一个小的自包含的,真实世界的例子REST服务使用的RDBMS。

The Simple Customer REST Example has a small self-contained, real-world example of creating a simple REST Service utilizing an RDBMS.

这篇关于推荐ServiceStack API结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆