我试图绕过ServiceStack
并利用它来展示RESTful服务。
我目前正在使用MVC / Service / Repository / UnitOfWork类型模式,其中获取客户的基本操作可能如下所示:
MVC Controller Action --> Service Method --> Repository --> SQL Server
我的问题是:
我想我有点困惑如何让所有这些并存。
域对象
public class Customer
{
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
查看模型
public class CustomerViewModel
{
public int Id {get;set;}
public string FirstName {get;set;}
....
}
控制器
public class CustomersController : Controller
{
ICustomerService customerService;
public CustomersController(ICustomerService customerService)
{
this.customerService = customerService;
}
public ActionResult Search(SearchViewModel model)
{
var model = new CustomersViewModel() {
Customers = customerService.GetCustomersByLastName(model.LastName); // AutoMap these domain objects to a view model here
};
return View(model);
}
}
服务
public class CustomerService : ICustomerService
{
IRepository<Customer> customerRepo;
public CustomerService(IRepository<Customer> customerRepo)
{
this.customerRepo = customerRepo;
}
public IEnumerable<Customer> GetCustomersByLastName(string lastName)
{
return customerRepo.Query().Where(x => x.LastName.StartsWith(lastName));
}
}
答案 0 :(得分:3)
首先,这只是个人偏好,我将摆脱您的存储库层,只是直接从服务操作访问/验证您的数据。如果您所做的只是传递参数,那么拥有所有这些额外的层是毫无意义的。
回答你的问题:
1)您的服务应该返回DTO(source),您提到您正在使用MVC应用程序,因此请确保您在操作中使用IReturn接口,这将允许您可以在控制器操作中执行var customers = client.Get(new GetCustomers());
之类的操作,请参阅here。您如何使用DTO,如果您愿意,可以将其用作ViewModel,如果您需要其他来源的其他属性,则可以创建单独的ViewModel。
2)是的,ServiceStack是您应用程序中的服务层,通常您将通过该层进行所有交互,不需要所有这些不同的层(上面我的第一点),为此,它看起来好像这个应用程序的架构比它需要的更复杂..
3)我认为是的,你似乎在考虑你的应用,切掉所有这些层
就上述示例而言,遵循建议here。我会做这样的事情:
项目结构(这些可以是一个项目中的文件夹,也可以根据应用程序的大小分成不同的项目:)
虽然对于只有少量服务的小型项目,可以将所有内容都放在一个项目中,并根据需要简单地扩展您的架构。
- SamProject.Web
App_Start
AppHost.cs
Controllers
CustomerController.cs
- SamProject.ServiceInterface
Services
CustomersService.cs
Translators // Mappings from Domain Object > DTO
CustomersTranslator.cs
- SamProject.Data // Assumes using EF
CustomersContext.cs
Customer.cs
- SamProject.ServiceModel
Operations
CustomersService
GetCustomers.cs
GetCustomer.cs
CreateCustomer.cs
Resources
CustomerDTO.cs
<强>代码强>
DTO:
public class CustomerDTO
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
操作:
[Route("/customers/{Id}")]
public class GetCustomer : IReturn<CustomerDTO>
{
public int Id { get; set; }
}
[Route("/customers")]
public class GetCustomers : IReturn<IEnumerable<CustomerDTO>>
{
public string LastName { get; set; }
}
服务:
public class CustomersService : Service
{
private readonly CustomerContext _dbCustomerContext;
public CustomersService(CustomerContext dbCustomerContext)
{
_dbCustomerContext = dbCustomerContext;
}
public object Get(GetCustomer request)
{
return _dbCustomerContext.Customers
.FirstOrDefault(c => c.Id == request.Id)
.Select(c => c.Translate());
}
public object Get(GetCustomers request)
{
if (string.IsNullOrEmpty(request.LastName))
{
return _dbCustomerContext.Customers.ToList()
.Select(c => c.Translate());
}
return _dbCustomerContext.Customers
.Where(c => c.LastName == request.LastName).ToList()
.Select(c => c.Translate());
}
}
控制器:
public class CustomersController : Controller
{
private readonly JsonServiceClient _client;
public CustomersController(JsonServiceClient client)
{
_client = client;
}
public ActionResult Search(SearchViewModel model)
{
var customers = _client.Get(new GetCustomers
{
LastName = model.LastName
});
return View(customers);
}
}
备注
Translate
是一种扩展方法,可以在Translators中使用,也可以使用内置的translator ServiceModel
我确实有一个明确定义的文件夹结构,但是,我的服务操作的命名空间只是SamProject.ServiceModel
而不是SamProject.ServiceModel.Operations.CustomersService
。但是,我的资源位于SamProject.ServiceModel.Resources
名称空间。