Just learning REST and ServiceStack and asking for suggestion how to build this example schema:
I have a User object with those fields:
public class User
{
public string ID {get;set;
public string Name {get;set;}
public List<int> OrderID {get;set;} // inner collection
// all other fields
}
I have a Service class:
public class UserService : Service
{
public List<User> Get(User UserRequest)
{
List<User> lstUsers = // Somehow polulate a collection of Users
return lstUsers;
}
// Other functions
}
and a AppHost file (self hosted for now)
public UserHost : AppHostHttpListenerBase
{
public override void Configure(Funq.Container container)
{
Routes
.Add<User>("/UserInfo")
.Add<User>("/User/{ID}");
}
}
Everything working fine: the client (browser) send an empty 'User' request and receive collection of User objects, but what I need to add is to get specific User request. For example I want to receive (and change) all Orders with specific User ID.
For example User with ID = 2 has a collection of 10 OrderID. So I though I can build an URI like this: /MyHost/2/Orders and it will return collection of Order objects.
I already tried to add another DTO object Order and bind it to routes like this:
Route.Add<Order>("/User/{ID}/Oders")
but it does not work. The screen (at least in browser) always stay blank and it seems no response is coming from SS.
Is it a RESFull way of doing things ? How It could be implemented in ServiceStack ? and could you provide a little code example (even schematic) how to do that ?
If you want to return a list of orders for a given user, then binding to the URL "/User/{ID}/Orders" is the RESTful way, yes.
With ServiceStack I normally prefer to define request and response classes, where request class will have all the possible input parameters and response defines the resulting object. Though often these to can be combined like User in the example.
As {ID} in the URL refers to the user ID, it's better to name it {UserID} and also have this property on your request class.
Probably you can just have UserID on the Order class:
public class Order
{
public string ID { get; set; } // order ID
public string UserID { get; set; } // user ID - also request param
// ...
}
Routes.Add<Order>("/User/{UserID}/Oders");
Now, UserID from the URL is mapped to your UserID property and you can use it to query the db, etc.
Each request class normally corresponds to another service class with your app logic. Thus,
for User you have UserService : RestServiceBase<User>,
for Order there is OrderService : RestServiceBase<Order>.
When ServiceStack sees this URL mapping Routes.Add<Order>("/User/{UserID}/Oders") it knows to invoke OrderService for a given URL.
public class OrderService : RestServiceBase<Order>
{
public override object OnGet(Order request)
{
// ...
}
}
Related
I have some properties in the object that corresponds to the request body, but I would like to hide them from Swagger UI documentation, because their purpose is just to work in the background along the request flow. I've tried some solutions to POST and GET requests, but when the request is sent by FormData and I have properties that are navigation properties (an object), the settings don't work and the information is shown in Swagger UI.
Let me give an example.
I have a class which is used to store (in memory) the logged in user data:
public class LoggedUser
{
public UserInfo(long id, string name)
{
Id = id;
Name = name;
}
public long Id { get; init; }
public string Name { get; init; }
}
And I have a class which is used as a base for the request body classes:
public abstract class RequestCommand
{
public LoggedUser User{ get; init; }
...
}
But these properties are shown in Swagger UI:
I've tried to use this solution: Ignore [FromForm] data from rendering on swagger
but when I have navigation properties like on the image above (User.Id, User.Name, ...) it does not work.
I would like to find a solution that can hide these properties from Swagger UI.
I'm looking to retain a ton of functionality I used to have in my codebase from the service layer that I exposed previously using OData services but through ServiceStack, assuming I implement the service logic, I don't want to have to make a ton of new DTO's for requests when this is essentially what i'm trying to achieve unless the framework "forces" me to declare a bunch of extra classes for no functional gain ...
[Route("~/{Type}")]
public class GetRequest
{
public string Type {get; set; }
public string Select { get; set; }
public string Expand { get; set; }
public string Filter { get; set; }
public string GroupBy { get; set; }
public string OrderBy { get; set; }
}
public ServiceBase<T> : Service
{
public virtual IEnumerable<T> Get(GetRequest<T> request) { ... }
}
public FooService : ServiceBase<Foo>
{
public override IEnumerable<Foo> Get(GetRequest<Foo> request) { ... }
}
The only other way I can see to implement this is to basically have to create a FooRequest DTO that inherits from the generic one here and adds nothing.
Whilst this might be the case in some scenarios, for the bulk of the hundreds of endpoints I have to migrate this just seems wasteful and likely will require to me having to result to code generation, something Service Stack claims "isn't needed".
My situation is made worse because I have "multiple data contexts" to consider for example ...
// base implementation for all services, derives from ServiceStack Service
public abstract class ServiceBase<T> : Service { ... }
// core service then one concrete implementation off that
public class CoreService<T> : ServiceBase<T> { ... }
public CoreFooService : CoreService<Foo> { ... }
/// b2b service then one concrete implementation off of that
public class B2BService<T> : ServiceBase<T> { ... }
public class BarB2BService : B2BService<Bar> { ... }
... with my OData based implementation I only need to add each new class to add a point of customisation for that type of data in the stack.
With ServiceStack this still seems to be possible regarding service classes (i think, but i'm not clear on how the routing works) ... where I get confused is understanding the request DTOs which are basically the same in all get requests but seemingly not routeable based on some tpye information in the URL.
Ideally I would like to route a standard Request DTO to a service method by a combination of the HTTP verb used and then something like [Route("~/{Context}/{Type}")] in the url (with that being the attribute usage on the DTO).
I get the feeling though that ServiceStack doesn't work like this and is going to require me to define a new DTO for literally every method on every service and i'm going to have to define a bunch of new services that don't exist with no new implementation details in them just to satisfy the frameworks needs.
Or am i missing some trick in how to use the framework here to avoid this work?
You can have multiple Service base classes but your Request DTO cannot be generic, it has to be a concrete Request DTO, but it can inherit base classes, e.g. All AutoQuery RDBMS Services inherit from QueryDb<T> or QueryDb.
Your Route should start with / (i.e. not ~/) and you could have a single Parameter that accepts any Type:
[Route("/data/{Type}")]
public class GetData
{
public string Type {get; set; }
public string Select { get; set; }
public string Expand { get; set; }
public string Filter { get; set; }
public string GroupBy { get; set; }
public string OrderBy { get; set; }
}
That can be called with:
GET /data/Anything
But your Service should have the same return Type (i.e. adhere to its Service Contract) so a wildcard Service is not going to be useful unless you return the same unstructured Data response like Dictionary<string,object>, List<object>, etc.
I get the feeling though that ServiceStack doesn't work like this and is going to require me to define a new DTO for literally every method on every service and i'm going to have to define a bunch of new services that don't exist with no new implementation details in them just to satisfy the frameworks needs.
Yes ServiceStack Requires every Service is defined by its Request DTO which is the master authority describing that Services contract. This is not just a requirement to appease the Framework, the Request DTO is the message that invokes a Service, which is the only thing generic Service Clients need to send to invoke a Service, which it can't send if it doesn't exist, nor can it have a Typed API (without code-gen) if there are no types.
Say I have a database in which I am storing user details of this structure:
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
}
I have a data access layer that works with this that contains methods such as GetById() and returns me a User object.
But then say I have an API which needs to return a users details, but not sensitive parts such as the PasswordHash. I can get the User from the database but then I need to strip out certain fields. What is the "correct" way to do this?
I've thought of a few ways to deal with this most of which involve splitting the User class into a BaseClass with non sensitive data and a derived class that contains the properties I would want kept secret, and then converting or mapping the object to the BaseClass before returning it, however this feels clunky and dirty.
It feels like this should be a relatively common scenario, so am I missing an easy way to handle it? I'm working with ASP.Net core and MongoDB specifically, but I guess this is more of a general question.
It seems for my purposes the neatest solution is something like this:
Split the User class into a base class and derived class, and add a constructor to copy the required fields:
public class User
{
public User() { }
public User(UserDetails user)
{
this.UserId = user.UserId;
this.Name = user.Name;
this.Email = user.Email;
}
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class UserDetails : User
{
public string PasswordHash { get; set; }
}
The data access class would return a UserDetails object which could then be converted before returning:
UserDetails userDetails = _dataAccess.GetUser();
User userToReturn = new User(userDetails);
Could also be done using AutoMapper as Daniel suggested instead of the constructor method. Don't love doing this hence why I asked the question but this seems to be the neatest solution and requires the least duplication.
There are two ways to do this:
Use the same class and only populate the properties that you want to send. The problem with this is that value types will have the default value (int properties will be sent as 0, when that may not be accurate).
Use a different class for the data you want to send to the client. This is basically what Daniel is getting at in the comments - you have a different model that is "viewed" by the client.
The second option is most common. If you're using Linq, you can map the values with Select():
users.Select(u => new UserModel { Name = u.Name, Email = u.Email });
A base type will not work the way you hope. If you cast a derived type to it's parent type and serialize it, it still serializes the properties of the derived type.
Take this for example:
public class UserBase {
public string Name { get; set; }
public string Email { get; set; }
}
public class User : UserBase {
public string UserId { get; set; }
public string PasswordHash { get; set; }
}
var user = new User() {
UserId = "Secret",
PasswordHash = "Secret",
Name = "Me",
Email = "something"
};
var serialized = JsonConvert.SerializeObject((UserBase) user);
Notice that cast while serializing. Even so, the result is:
{
"UserId": "Secret",
"PasswordHash": "Secret",
"Name": "Me",
"Email": "something"
}
It still serialized the properties from the User type even though it was casted to UserBase.
If you want ignore the property just add ignore annotation in you model like this, it will skip the property when model is serializing.
[JsonIgnore]
public string PasswordHash { get; set; }
if you want ignore at runtime(that means dynamically).there is build function avilable in Newtonsoft.Json
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
//FYI ShouldSerialize_PROPERTY_NAME_HERE()
public bool ShouldSerializePasswordHash()
{
// use the condtion when it will be serlized
return (PasswordHash != this);
}
}
It is called "conditional property serialization" and the documentation can be found here. hope this helps
The problem is that you're viewing this wrong. An API, even if it's working directly with a particular database entity, is not dealing with entities. There's a separation of concerns issue at play here. Your API is dealing with a representation of your user entity. The entity class itself is a function of your database. It has stuff on it that only matters to the database, and importantly, stuff on it that does not matter to your API. Trying to have one class that can satisfy multiple different applications is folly, and will only lead to brittle code with nested dependencies.
More to the point, how are you going to interact with this API? Namely, if your API exposes your User entity directly, then any code that consumes this API either must take a dependency on your data layer so it can access User or it must implement its own class representing a User and hope that it matches up with what the API actually wants.
Now imagine the alternative. You create a "common" class library that will be shared between your API and any client. In that library, you define something like UserResource. Your API binds to/from UserResource only, and maps that back and forth to User. Now, you have completely segregated your data layer. Clients only know about UserResource and the only thing that touches your data layer is your API. And, of course, now you can limit what information on User is exposed to clients of your API, simply by how you build UserResource. Better still, if your application needs should change, User can change without spiraling out as an API conflict for each consuming client. You simply fixup your API, and clients go on unawares. If you do need to make a breaking change, you can do something like create a UserResource2 class, along with a new version of your API. You cannot create a User2 without causing a whole new table to be created, which would then spiral out into conflicts in Identity.
Long and short, the right way to go with APIs is to always use a separate DTO class, or even multiple DTO classes. An API should never consume an entity class directly, or you're in for nothing but pain down the line.
I am working on an Azure Mobile Apps project. Where I have to define a Table Controller with that can accept two parameters and give a list of values. I have a DataObject for ProductItem, which is
public class ProductItem : EntityData
{
public string Name { get; set; }
public string Details { get; set; }
public double Price { get; set; }
public string Image { get; set; }
public Merchant Merchant { get; set; }
}
I need to get a specific Product item, filter by its Price and Merchant. Already in the ProductItemContoller, I have scaffolded
// GET tables/ProductItem
public IQueryable<ProductItem> GetAllProductItems()
{
return Query();
}
// GET tables/ProductItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<ProductItem> GetProductItem(string id)
{
return Lookup(id);
}
by looking at existing examples. But in examples, we have not called any of the given methods from Client. Rather, IEnumerable<ProductItem> items = await productTable.ToEnumerableAsync(); was called.
My question is why can't we call GetAllProductItems() which was already defined in the controller to the client. If we can call, how to do it.
And also, I need to have a controller method, I need to have a GetAllProductByMerchat(string merchantId). How can I make this possible.
The Table controllers are called automatically by the client SDKs on your behalf, allowing you to work with LINQ queries on the client. You can use something like:
var items = productTable.Where(p => p.Price < 100).ToListAsync();
This gets translated into an OData query across the wire, then translated back into a LINQ query on the server, where it then gets translated into SQL and executed on the SQL Azure instance.
For more information, see chapter 3 of http://aka.ms/zumobook
Did you mean this?
// Server method:
[HttpGet]
[Route("GetAllProductItems")]
public IQueryable<ProductItem> GetAllProductItems()
{
return Query();
}
// Client call
var result = await MobileService.InvokeApiAsync<IQueryable<ProductItem>>("ProductItem/GetAllProductItems", HttpMethod.Get, null);
Remember to add these attribute before the ProductItemController:
[MobileAppController]
[RoutePrefix("api/ProductItem")]
You can do the same thing to your GetAllProductByMerchat(string merchantId) method.
I am looking for the most appropriate way of dealing with a user activity feed on my social networking site. At the moment i have several activities which can appear on the news feed such as:
Users joins the site
User comments on a post
User adds a post to their favorites
User adds a new post to the site
Here is a simplified version of my domain objects at the moment:
public abstract class NewsItem : Entity, ITenantSpecific
{
public virtual Account Account { get; set; }
public virtual DateTime DateTime { get; set; }
// returns formatted news html string which gets
// overridden by inherted classes
public abstract string GetNewsHtml();
}
public class NewsItemJoiner : NewsItem
{
public virtual Account AccountJoined { get; set; }
public override string GetNewsHtml()
{
return "XXX has just joined our music network";
}
}
As you can see at the moment I have a property which must be overridden on each activity called GetNewsHtml. This isn't ideal as I don't believe my domain should be responsible for generating my HTML.
I have thought about using a partial view for each activity type and pass into it the NewsItem base class downcasted into the correct type.
However I am open to suggestions.
I have a similar issue but with different order types. I decided to define rendering at the view layer (web/controllers), not domain. You can do it this way:
public interface IRenderer<T> where T: NewsItem
{
string Render(T item);
}
public class NewsItemJoinerRenderer: IRenderer<NewsItemJoiner>
{
public string Render(T item)
{
return "XXX has just joined our music network";
}
}
public class NewsRendererFactory
{
public IRenderer<T> GetRenderer<T>()
{
return ServiceLocator.GetInstance<IRenderer<T>>();
}
}
Then you can pass NewsRendererFactory to controller. Perhaps there's a way to avoid ServiceLocator but for now I cannot tell.
Notice that this makes your architecture both configurable and pluggable if needed.
You can define additional render-related interfaces, add more properties to the IRenderer - for example, PartialName, etc, or have lambda filters on IRenderer that Factory uses to decide if this interface implementation is applicable for the passed (to GetRenderer("some-condition")) condition. A lot of things are possible.
If you don't want IoC containers (ServiceLocator), you can have its job done with simple switch() statement inside NewsRendererFactory.GetRenderer. This will isolate the logic inside single factory method, and you'll be able to replace it easily with true IoC once you are ready.
Update: how to get renderers.
If you don't use IoC, you do something like
typeof(IRenderer<>).Assembly.GetTypes().Where(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IRenderer<>) &&
x.GetGenericArguments().FirstOrDefault() == requestedTypeArguments)
Then you can select SingleOrDefault() or ToList() if you can handle multiple renderers.