Kid*_*man 2 c# asp.net asp.net-web-api asp.net-web-api2
我是构建Web API的新手,已经达到了可以使用某个方向的程度.因此,举个例子说我有一个Product模型和一个Attachment看起来像这样的模型:
public class Product
{
public Product()
{
Attachments = new List<Attachment>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<Attachment> Attachments { get; set; }
}
public class Attachment
{
public int ID { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
请注意,Product模型具有类型的属性列表Attachment.AttachmentRepository当我Property在ProductRepository类中初始化对象时,利用填充此属性是不好的做法?
所以ProductRepository我会做这样的事情:
Product product = new Product
{
ID = SomeId,
Name = SomeName
Attachments = AttachmentRepository.GetAttachments(SomeName)
};
Run Code Online (Sandbox Code Playgroud)
这是一个糟糕的设计,我接近这个错误?我不打算创建一个Controller,Attachment因为在没有a的上下文的情况下获取附件没有用例Product.
"我不打算创建一个Controller for Attachment,因为在没有产品上下文的情况下获取附件没有用例."
反过来怎么样?您是否想要获得没有附件的产品?
我发现尝试做太多而不是可重用的方法,因为如果我获得大量产品并且对附件不感兴趣,我不希望获得所有这些产品的附件的开销.然后我后悔设计(无论是我的还是同事),为了获得产品而添加了一种新方法.
在我的控制器中,我将调用GetProduct,然后调用GetAttachments.这将允许您根据需要混合匹配这些.
另一种方法是在Products存储库中执行此操作,使用只获取产品的方法(GetProducts),以及调用GetProducts并调用GetAttachments的另一个GetProductsWithAttachments方法.或者你当然可以有一个布尔参数, includeAttachments = false).我不喜欢我的数据库层变得那么混乱.我让控制器成为了把它们拉到一起的地方.
我甚至可能在Products模型中没有Attachments属性,而是具有特定于控制器的ProductResponseModel,它类似于ViewModel.它将是包含产品信息和Attachments属性的那个,并且您将从调用两个单独的Repository方法的结果中填充它.
如果您在数据库层执行所有操作,并且数据库层中的产品模型具有仅在调用GetProductsWithAttachments时填充的附件属性,则您的产品模型将填充一半. 随着时间的推移添加许多其他类似的属性,并且您有一个非常令人困惑的模型,因为有时只根据您调用的存储库的哪个方法填充其某些属性.开发人员必须开始深入研究repo方法,以找出填充内容的方法.如果您将促销添加到产品,您将获得GetProductWithAttachments,GetProducts,GetProductWithPromotions,GetProductWithAttachmentsAndPromotions?你可以开始看看这是如何失控的,如果你真的想把它加入你的存储库,一些默认参数会更好.然而:
这就是为什么我的偏好是让控制器协调整个事情.在控制器内单独调用repo方法.不确定您是使用REST样式还是Web API控制器中的内容,因此请考虑以下伪代码:
public class ProductController: ApiController
{
public ProductResponseModel Get(int productId)
{
var model = new ProductResponseModel{
Product = ProductRepository.Get(productId);
};
model.Attachments = AttachmentRepository.GetList(model.Product.Name);
// I could have flattened out the Product into its properties instead of having a model.Product,
// but that can be a maintenance problem and requires something like AutoMapper to manage well
return model;
}
}
public class ProductResponseModel {
public Product Product {get;set;}
public IEnumerable<Attachment> Attachments {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
ProductResponseModel是一个组合示例.它创建了与DB层的松散耦合,因此您可以自由混合和匹配,即组合每个API控制器所需的数据模型.ProductResponseModel本身不是非常可重用的,可能只在该控制器内.另一个需要不同产品数据组合的控制器将拥有自己的SomethingResponseModel并调用单独的Repository方法来填充它. 尽管我们没有重用我们的*ResponseModels,但这并不是一个很大的损失,因为它们是简单的POCO.从我们的repo方法中重用是更重要的,并且避免它们变得比它们需要的更复杂. 此外,我们仍然拥有您的简单模型,例如Product,Attachment它们是存储库层的一部分,因此调用repo的每个人都使用相同的语言并使用相同的常见类型.因此,不要错误地让Repo层返回ProductResponseModel.这是你的控制器的工作,采取Product和填充ProductResponseModel.
我使用命名约定*ResponseModel,因为如果我也有一个复杂的action参数参数,那么也有一个*RequestModel.即请求/响应.如果我有一个比REST风格更具RPC样式的API方法,例如ProductController.DiscontinueDistribution,它的返回可能非常专业,所以我有一个ProductDiscontinueDistributionResponseModel.这些都是简单的POCO,就像MVC中的ViewModel一样.
| 归档时间: |
|
| 查看次数: |
1812 次 |
| 最近记录: |