ServiceStack请求和响应对象 [英] ServiceStack Request and Response Objects

查看:280
本文介绍了ServiceStack请求和响应对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它是确定(读好的做法),再使用POCO的请求和响应DTO的。我们POCO的是轻量级(ORM精简版)仅具有性能和一些装饰属性。



或者,我应该创建请求和/或响应其它物体?



谢谢,


解决方案

我会说这取决于你的系统,最终如何大而复杂的,现在,和有可能成为潜在。



ServiceStack文件没有明确规定应该使用哪种设计模式。最终它提供了灵活性用于分离数据库模型POCO的距离的DTO,但它也提供了用于其再利用支持



当使用OrmLite:



OrmLite的设计,让你可以重新使用的数据模型作为波苏斯您的请求和响应的DTO。 由于从ServiceStack文档指出,这是一个该框架的设计故意目标:




在波苏斯ORMS微被使用,再利用作为DTO的,因为他们没有特别适合包含任何循环引用的重型奥姆斯有(如EF)。 OrmLite进1步进一步,并借用来自网页的NoSQL的剧本,其中任何复杂的财产如名单是透明blobbed在一个无模式的文本字段,促进由RDBMS关注不羁摩擦纯POCOS的设计。




代价:



如果你选择重新使用波苏斯,因为它是支持的,你应该知道,在有些情况下这将是更聪明的使用单独的请求和响应DTO的情况。




< STRONG>在许多情况下这些POCO数据模型已经做好的DTO,可直接代替返回映射到特定领域的DTO的。




^并非所有情况下。有时选择设计图案的难度预见的情况下,它可能不适合于重新使用。所以希望一个场景将有助于说明一个潜在的问题。



情景:




  • 你有一个系统,用户可以为注册服务。

  • 您,作为管理员,必须列出你的服务用户的能力。



如果你把OrmLite POCO再利用的方法,那么我们可能有这样的用户 POCO:

 公共类用户
{
[PrimaryKey的,自动递增,别名(ID)]
公众诠释用户ID {搞定;组; }
公共字符串用户名{获得;组; }
公共字符串密码{搞定;组; }
公共字符串盐{搞定;组; }
公共BOOL启用{搞定;组; }
}

当你让你的创建用户的要求,你填充用户名密码你的用户的 POCO作为您的要求,到服务器



我们不能只推这个POCO到数据库,因为:




  • 密码密码字段将是纯文本。我们是优秀的程序员,和安全是很重要的,所以我们需要建立我们添加到属性的盐和散列密码与盐和更新密码字段。 OK,这不是一个大问题,的几行代码将排序,插入前。


  • 客户端可能会设置一个用户ID ,但对于创造这不是必需的,会造成我们的数据库查询失败插入。因此,我们必须插入到数据库之前默认此值。


  • 已启用属性可能已该请求通过。如果有人有什么设了这个?我们只希望处理用户名密码,但现在我们不得不考虑其他领域,将影响数据库插入。同样他们可以设置(虽然这不会是因为我们无论如何覆盖价值的问题。)的好,你现在添加了验证做




但现在考虑的时候,才返回列表<使用者名称> ;



如果您重新使用POCO作为响应类型,还有很多领域,你不想暴露回到客户端。它不会是聪明的事:

 返回Db.Select<使用者>(); 

由于你没有上市,用户紧密特定目的建造的响应,密码散列值和将需要以防止它在响应中被序列化了的逻辑被删除。



此外还应考虑到用户在注册过程中,随着创建请求的一部分,我们要问我们是否应该发送欢迎电子邮件。因此,我们将更新POCO:

 公共类用户
{
//属性为$ B前$ b ...
[忽略] //这不是一个数据库字段
公共BOOL SendWelcomeEmail {搞定;组; }
}

我们现在有额外的属性,只有在用户创建过程中有用。如果您使用用户 POCO一遍又一遍,你会发现随着时间的推移,你要增加并不适用于某些情况下越来越多的属性。



当我们返回的用户列表,例如,现在 SendWelcomeEmail 的可选属性,可以填充 - 它只是没有按T意义。然后它可以是难以维持的代码



要记住的关键一点是,共享,使得它同时作为请求和响应对象的POCO对象时: 您发送一个响应将在请求中暴露的属性。您将不得不做的请求更多的验证,该POCO的最终共享可能不省力。



 公共类CreateUserRequest $ b $:

在这种情况下不会是做容易得多b {
公共字符串用户名{获得;组; }
公共字符串密码{搞定;组; }
公共BOOL SendWelcomeEmail {搞定;组; }
}

公共类UserResponse
{
公众诠释用户ID {搞定;组; }
公共字符串用户名{获得;组; }
公共BOOL启用{搞定;组; }
}

公共类用户
{
[PrimaryKey的,自动递增,别名(ID)]
公众诠释用户ID {搞定;组; }
公共字符串用户名{获得;组; }
公共字符串密码{搞定;组; }
公共字符串盐{搞定;组; }
公共BOOL启用{搞定;组; }
}

我们现在知道,当我们创建一个请求( CreateUserRequest ),我们不必考虑用户ID 已启用



在返回的用户列表它现在列表< UserResponse> 并没有机会在客户端将看不到任何性能我们不希望他们看到的。



很明显给其他人看代码,请求所需的性能,又会有怎样的反应暴露出来。



摘要:



对不起,这是一个很长的答案,但我认为这解决了共享波苏斯一个方面的有些人错过了,或没有初步掌握,我是其中之一。




  • 是的,你可以重新使用波苏斯请求和响应。

  • 的文件说,这是确定这样做。事实上,它是由设计。

  • 在许多情况下,将被罚款再使用。

  • 有它不适合的情况。 (我的情况下试图证明这一点,但你会发现当你开发自己的实际情况。)

  • 考虑有多少额外的属性可能会暴露,因为你的共享POCO试图支持多个操作,多少额外的验证工作可能需要。

  • 归根结底这是关于你是舒服维护的。



希望这有助于。


Is it ok (read good practice) to re-use POCO's for the request and response DTO's. Our POCO's are lightweight (ORM Lite) with only properties and some decorating attributes.

Or, should I create other objects for the request and/or response?

Thanks,

解决方案

I would say it depends on your system, and ultimately how big and complex it is now, and has the potential to become.

The ServiceStack documentation doesn't specify which design pattern you should use. Ultimately it provides the flexibility for separating the database model POCO's from the DTOs, but it also provides support for their re-use.

When using OrmLite:

OrmLite was designed so that you could re-use your data model POCOs as your request and response DTOs. As noted from the ServiceStack documentation, this was an intentional design aim of the framework:

The POCOs used in Micro ORMS are particularly well suited for re-using as DTOs since they don't contain any circular references that the Heavy ORMs have (e.g. EF). OrmLite goes 1-step further and borrows pages from NoSQL's playbook where any complex property e.g. List is transparently blobbed in a schema-less text field, promoting the design of frictionless Pure POCOS that are uninhibited by RDBMS concerns.

Consideration:

If you do opt to re-use your POCOs, because it is supported, you should be aware that there are situations where it will be smarter to use separate request and response DTOs.

In many cases these POCO data models already make good DTOs and can be returned directly instead of mapping to domain-specific DTOs.

^ Not all cases. Sometimes the difficulty of choosing your design pattern is foreseeing the cases where it may not be suitable for re-use. So hopefully a scenario will help illustrate a potential problem.

Scenario:

  • You have a system where users can register for your service.
  • You, as the administrator, have the ability to list users of your service.

If you take the OrmLite POCO re-use approach, then we may have this User POCO:

public class User
{
    [PrimaryKey, AutoIncrement, Alias("Id")]
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Salt { get; set; }
    public bool Enabled { get; set; }
}

When you make your Create User request you populate Username and Password of your User POCO as your request to the server.

We can't just push this POCO into the database because:

  • The password in the Password field will be plain text. We are good programmers, and security is important, so we need to create a salt which we add to the Salt property, and hash Password with the salt and update the Password field. OK, that's not a major problem, a few lines of code will sort that before the insert.

  • The client may have set a UserId, but for create this wasn't required and will cause our database query to fail the insert. So we have to default this value before inserting into the database.

  • The Enabled property may have been passed with the request. What if somebody has set this? We only wanted the deal with Username and Password, but now we have to consider other fields that would effect the database insert. Similarly they could have set the Salt (though this wouldn't be a problem because we would be overriding the value anyway.) So now you have added validation to do.

But now consider when we come to returning a List<User>.

If you re-use the POCO as your response type, there are a lot of fields that you don't want exposed back to the client. It wouldn't be smart to do:

return Db.Select<User>();

Because you don't have a tight purpose built response for listing Users, the Password hash and the Salt would need to be removed in the logic to prevent it being serialised out in the response.

Consider also that during the registration of a user, that as part of the create request we want to ask if we should send a welcome email. So we would update the POCO:

public class User
{
    // Properties as before
    ...
    [Ignore] // This isn't a database field
    public bool SendWelcomeEmail { get; set; }
}

We now have the additional property that is only useful in the user creation process. If you use the User POCO over and over again, you will find over time you are adding more and more properties that don't apply to certain contexts.

When we return the list of users, for example, there is now an optional property of SendWelcomeEmail that could be populated - it just doesn't make sense. It can then be difficult to maintain the code.

A key thing to remember is that when sharing a POCO object such that it is used as both a request and response object: Properties that you send as a response will be exposed in a request. You will have to do more validation on requests, ultimately the sharing of the POCO may not save effort.

In this scenario wouldn't it be far easier to do:

public class CreateUserRequest
{
    public string Username { get; set; }
    public string Password { get; set; }
    public bool SendWelcomeEmail { get; set; }
}

public class UserResponse
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public bool Enabled { get; set; }
}

public class User
{
    [PrimaryKey, AutoIncrement, Alias("Id")]
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Salt { get; set; }
    public bool Enabled { get; set; }
}

We know now when we create a request (CreateUserRequest) that we don't have to consider UserId, Salt or Enabled.

When returning a list of users it's now List<UserResponse> and there is no chance the client will see any properties we don't want them to see.

It's clear to other people looking at the code, the required properties for requests, and what will be exposed in response.

Summary:

Sorry, it's a really long answer, but I think this addresses an aspect of sharing POCOs that some people miss, or fail to grasp initially, I was one of them.

  • Yes you can re-use POCOs for requests and response.
  • The documentation says it's OK to do so. In fact it is by design.
  • In many cases it will be fine to re-use.
  • There are cases where it's not suitable. (My scenario tries to show this, but you'll find as you develop your own real situations.)
  • Consider how many additional properties may be exposed because your shared POCO tries to support multiple actions, and how much extra validation work may be required.
  • Ultimately it's about what you are comfortable maintaining.

Hope this helps.

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

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