2 回答

TA貢獻1998條經驗 獲得超6個贊
首先,“最佳”解決方案是一個相當主觀的術語。我通常的目標是干燥,可重復使用,高性能的解決方案,促進最小的努力,摩擦和chattiness,而其他人可能會定義“最佳”,它遵循REST的原則。因此,根據目標的不同,您將獲得不同的響應。我只能提供如何處理它。
ServiceStack服務實現從其自定義路由中解耦
需要記住的一件事是,您在ServiceStack中定義和設計服務的方式與您公開它們的方式完全脫離,因為您可以在任何自定義路徑下公開您的服務。ServiceStack鼓勵基于消息的設計,因此您應該為每個操作提供不同的消息。
使用邏輯/分層Url結構
我使用邏輯Url結構,我的目標是表示名詞的標識符,它是分層結構的,即父路徑對您的資源進行分類并為其提供有意義的上下文。因此,在這種情況下,如果您想公開事件和評論,我傾向于使用以下url結構:
/events //all events/events/1 //event #1/events/1/reviews //event #1 reviews
這些資源標識符中的每一個都可以應用任何HTTP謂詞
履行
對于實現,我通常遵循基于消息的設計,并基于響應類型和調用上下文對所有相關操作進行分組。為此我會做類似的事情:
[Route("/events", "GET")][Route("/events/category/{Category}", "GET")] //*Optional top-level viewspublic 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")] //*Optionalpublic 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; }}
并按照類似的模式進行活動評論
[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; }}
基于這些消息,實現應該是相當直接的,這些消息(取決于代碼庫大?。┪覍⒃?個EventsService和EventReviewsService類中組織。我應該注意,我自己使用多個服務請求DTO名稱,以避免與同名的數據模型發生沖突。
雖然我已經分開UpdateEvent
并CreateEvent
在這里,但StoreEvent
如果用例允許,我有時會將它們合并為一個冪等操作。
物理項目結構
理想情況下,根級AppHost項目應保持輕量級且無實現。雖然對于只有少量服務的小型項目,可以將所有內容都放在一個項目中,并根據需要簡單地擴展您的架構。
對于中型到大型項目,我們建議使用下面的物理結構,為了本示例的目的,我們假設我們的應用程序稱為EventMan。
項目的順序也顯示其依賴關系,例如頂級EventMan
項目引用所有子項目,而最后一個EventMan.ServiceModel
項目引用無:
- 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 - 您可以將其與任何通用C#服務客戶端一起使用以提供結束沒有任何代碼的端到端類型的API。
更新
此推薦的項目結構現在包含在所有ServiceStackVS的VS.NET模板中。
在簡單的客戶REST示例有創建一個簡單的REST服務利用RDBMS的小型自包含的,真實的例子。
- 2 回答
- 0 關注
- 809 瀏覽
添加回答
舉報