2 回答

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