More ServiceStack request DTO advice - servicestack

This is a follow up regarding:
ServiceStack Request DTO design
In the above question the design was strictly regarding read operations. What about write operations? Say we wanted to add operations for creating a new booking limit, would reusing the noun be appropriate here?
[Route("/bookinglimits/","POST")]
public class CreateBookingLimit : IReturn<BookingLimit>
{
BookingLimit newBookingLimit
}
-OR- Would this be better design?
[Route("/bookinglimits/","POST")]
public class CreateBookingLimit : IReturn<BookingLimit>
{
public int ShiftId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Limit { get; set; } }
}
Also, if we wanted to add editing--should we have insert and edit share the same models and add the ID?
[Route("/bookinglimits/","POST")]
[Route("/bookinglimits/{Id}/","PUT")]
public class CreateBookingLimit : IReturn<BookingLimit>
{
public int Id { get; set; }
public int ShiftId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Limit { get; set; } }
}
I'm trying to wrap my head around when it makes the most sense to reuse POCOs and when it makes more sense to separate intentions.

Message-based API Design
There are a few things to bear in mind when designing the ideal message-based API where your Services effectively end up serving 2 masters: a Native Client API and a REST API. Native Clients just send and receive messages in their original form so they get a natural API for free modelled using C# Request and Response DTOs to capture what information is required for the Service to perform its Operation and what it should return.
Projecting messages into the ideal HTTP API
After designing your message-based API you'll then want to focus on how best to project the messages into a REST API by annotating Request DTOs with [Route] Attributes to define the Custom endpoints for your Services.
This previous answer on Designing a REST-ful service with ServiceStack provides examples on which routes different Request DTOs map to, in general you'll want to design your APIs around Resources where each operation "acts on a Resource" which will make defining your Custom Routes easier. The ideal HTTP API for Creating and Updating a Booking Limit would look like:
POST /bookinglimits (Create Booking Limit)
PUT /bookinglimits/{id} (Update Booking Limit)
General recommendations on good API Design
Whilst not specifically about Web Services this article on Ten Rules for Good API Design provides good recommendations on general (Code or Services) API design. As API Consumers are the intended audience of your APIs who'll primarily be deriving the most value from them, their design should be optimized so that they're self-descriptive, use consistent naming, are intuitive to use and can be evolved without breaking existing clients. Messages are naturally suited to versioning but you still need to be mindful when making changes to existing published APIs that any additional properties are optional with default fallback behavior if required.
For this reason whilst you can save some code by returning a naked BookingLimit, my preference is to instead return a specific Response DTO for each Service which allows the Service to return additional metadata without breaking existing clients whilst maintaining a consistent Request/Response pattern for all Services. Although this is just my preference - returning naked types is also fine.
ServiceStack Implementation
To implement this in ServiceStack I wouldn't use the same Request DTO to support multiple verbs. Since the Request DTO is called Create* that conveys that users should only send this Request DTO to Create Booking limits which is typically done using a POST request, e.g:
[Route("/bookinglimits", "POST")]
public class CreateBookingLimit : IReturn<CreateBookingLimitResponse>, IPost
{
public int ShiftId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Limit { get; set; }
}
public class CreateBookingLimitResponse
{
public BookingLimit Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
The IPut, IPost are Verb interface markers which lets both the User and Service Client know which Verb this message should be sent with which makes it possible to have all messages sent in a single Service Gateway method.
If your Service also supports updating a Booking Limit then I'd create a separate Service for it which would look like:
[Route("/bookinglimits/{Id}", "PUT")]
public class UpdateBookingLimit : IReturn<UpdateBookingLimitResponse>, IPut
{
public int Id { get; set; }
public int ShiftId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Limit { get; set; }
}
public class UpdateBookingLimitResponse
{
public BookingLimit Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
By using separate Operations you can ensure Request DTOs contains only the properties relevant to that operation, reducing the confusion for API consumers.
If it makes sense for your Service, e.g. the schemas for both operations remains the same I'll merge both Create/Update operations into a single Operation. When you do this you should use a consistent Verb that indicates when an operation does both, e.g. Store* or CreateOrUpdate*:
[Route("/bookinglimits", "POST")]
public class StoreBookingLimit : IReturn<StoreBookingLimitResponse>, IPost
{
public int Id { get; set; }
public int ShiftId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Limit { get; set; }
}
public class StoreBookingLimitResponse
{
public BookingLimit Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
In most cases where the Server generates the Id for the Resource you should use POST, in the rare case where the client specifies the Id, e.g. Slug or Guid you can use PUT which roughly translates to "PUT this resource at this location" which is possible when the client knows the url for the resource.
Message based API examples
Most of the time what messages should contain will be obvious based on the Service requirements and becomes intuitive and natural to create over time. For examples on a comprehensive message-based API you can have a look AWS Web Services who've effectively servicified their Web Services behind a message-based design that uses Service Clients to send messages to access all their APIs, e.g. AWS DynamoDB API Reference lists each Actions that's available as well as other DTO Types that the Services return, e.g here are DynamoDB APIs they have around Creating / Modifying and Querying Items:
Actions
BatchGetItem
BatchWriteItem
DeleteItem
GetItem
PutItem
Query
Scan
UpdateItem
Data Types
AttributeDefinition
AttributeValue
AttributeValueUpdate
Condition
...
In ServiceStack Actions are called Operations and what you'll use Request DTOs to define, whilst AWS Data Types are just called DTOs which I keep in a Types namespace to differentiate from Operations.
DynamoDb.ServiceModel (project)
/GetItem
/PutItem
/UpdateItem
/DeleteItem
/Query
/Scan
/Types
/AttributeDefinition
/AttributeValue
/AttributeValueUpdate
You typically wouldn't need additional explicit Services for Batch Requests as you can get that for free using ServiceStack's Auto Batched Requests. ServiceStack also includes a number of other benefits where it's able to generate richer DTOs containing Custom Attributes and interfaces in the Source DTOs to enable a richer and succinct end-to-end typed API requiring less boilerplate and generated code that lets you use the same Generic Service Client to call any ServiceStack Service offering both Sync and idiomatic Async APIs. The additional metadata also enables seamless higher-level functionality like Encrypted Messaging, Cache Aware Clients, Multiple Formats, Service Gateway, HTTP Verb Interface Markers, etc.
Otherwise AWS follows a very similar approach to ServiceStack for designing message-based APIs using generic Service Clients to send DTOs native in each language.

Related

Change Autoquery return type in DTO generation

I want to return a custom class from my custom AutoQuery endpoint that inherits QueryResponse<T> but adds a few extra properties.
public class WritingAssignmentBlogLookUpResponse : QueryResponse<BlogDto>, IResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string DebugMessage { get; set; }
}
But if I specify request like so:
[Route("/assignment/blogs/", "POST")]
public class WritingAssignmentBlogsLookUpRequest : QueryDb<Blog, BlogDto>, IReturn<WritingAssignmentBlogLookUpResponse>
{
}
Then the return type specified in generatd DTO for client.post(req) is QueryResponse<BlogDto> and it doesn't generate WritingAssignmentBlogLookUpResponse at all.
Do I just have to specify return type as any from my typescript service or is there a way to make the types match so I can strongly type it?
You can’t change AutoQuery responses which are already fixed in their service contract definition to return a QueryResponse<T>.
You can add extra info to the Meta Dictionary of the Response DTO (exists for this reason) otherwise if you need to change the Service Contract you’d need to convert it into a normal (I.e. non-AutoQuery) API which could use the Service Gateway to call an existing AutoQuery API that decorates the response.

Get request with multiple inputs in ServiceStack API

I am creating a endpoint that accepts multiple parameters. I was wondering what the proper way of doing this in ServiceStack is, as I know that the routes can be defined like this:
[Route("/Cars/{EquipmentIds}/{ManufacturerIds}/{ColourIds}")]
But does not that mean that EquipmentIds has to be defined before ManufacturerIds and ColourIds, otherwise the API will interpret it incorrectly?
I would like to specify the parameters I use, and then not include the rest when they are not used.
A unclean url would then look like this ?EquipmentIds=1&ColourIds=1
I found the following solution, but this one was from 2011
Multiple Optional Parameters with ServiceStack.Net.
Is there a new solution for this, or is that still the proper way of doing things?
The URL should be a "resource identifier" where any Query String arguments are modifiers to that resource request.
So you shouldn't put complex types in the /path/info which are unlikely to form part of Resource Identifier for that route.
Your route should be self-describing as to what it's a resource identifier of. Stuffing a an anonymous bunch of ids in the URL doesn't make it a clean URL, it still needs to be semantically correct and self-describing at what the different path components contain.
It's hard to know the right Route to use when it's not clear what Service this is used for, but if this was a Car Search Service the appropriate URL would be something like:
/cars/search?EquipmentIds=1,2,3&ManufacturerIds=4,5,6&ColourIds=7,8,9
Just as when you use a Search Service like Google, they don't try to pack everything in the route, which is only used to identify you're making a search request. Everything else including the search query is added to the query string, e.g;
https://www.google.com/search?q=test
Which in ServiceStack would just be defined as:
[Route("/cars/search")]
public class SearchCars
{
public List<int> EquipmentIds { get; set; }
public List<int> ManufacturerIds { get; set; }
public List<int> ColourIds { get; set; }
}
Or it can be easily auto implemented in AutoQuery with:
[Route("/cars/search")]
public class SearchCars : QueryDb<Car>
{
public List<int> EquipmentIds { get; set; }
public List<int> ManufacturerIds { get; set; }
public List<int> ColourIds { get; set; }
}

How do I perform model binding on a HTTP POST in Azure Functions?

I want to bind my HTTP POST parameters to Azure functions, and want to ensure the untrusted data is correctly mapped to my model class.
Right now I'm using a mime type of application/json , and I may need to also support FORM Post and Protobuf.
Since I know support for the latter is a bit complex, how can I perform simple model binding for JSON data?
I've spent a lot of time reading about HTTP triggers, skimming all pages of the Azure Function docs, but don't see anything that helps with this issue. I suspect there is a lower level technology I need to research (webjobs?) for this.
If your HttpTrigger function is configured to accept JSON POST requests, you can bind to your custom model type as follows:
using System.Net;
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public static async Task<HttpResponseMessage> Run(Person person, HttpRequestMessage req)
{
return person.FirstName == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Who are you?")
: req.CreateResponse(HttpStatusCode.OK, $"Hello {person.FirstName}!");
}

CRUD and Query with ServiceStack - Need to get rid of some confusion

I am a bit confused with ServiceStack 'old' and 'new' API and need some clarification and best practices, especially with Request / Response DTO's and routing. I watched some courses on Pluralsight and have the first three books listet on servicestack.net in my electronic bookshelf.
I like to 'restify' an existing application which is built using DDD patterns which means I have a high level of abstraction. The client is WPF and follows the MVVM pattern. I have 'client side service', 'server side service' and repository classes (and some aggregates too). I use NHibernate 4 (with fluent API and a code-first approach) as ORM. Only my repository classes know about the ORM. I have DTO's for all my Entity objects and in my WPF client I only work with those DTOs in the ViewModel classes. I heavily use AutoMapper to 'transfer' Entity objects to my DTO's and vice versa.
My confusion starts exactly with these DTO's and the Request / Response DTOs used in ServiceStack. Here is a very much simplified example of an Address Entity which illustrates the problem:
All my Entity Objects derive from EntityBase which contains basic properties used in all Entities:
public abstract class EntityBase : IEntity
{
public virtual Guid Id { get; protected set; }
public virtual DateTime CDate { get; set; } //creation date
public virtual string CUser { get; set; } //creation user
public virtual DateTime MDate { get; set; } //last modification date
public virtual string MUser { get; set; } //last modification user
//
// some operators and helper methods irrelevant for the question
// ....
}
public class Address : EntityBase
{
public string Street { get; private set; }
public string AdrInfo1 { get; private set; }
public string AdrInfo2 { get; private set; }
public string ZipCode { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
}
Of course there are collections and references to related objects which are ignored here as well as database mappers, naming conventions etc. The DTO I have looks like this:
public class AddressDto
{
public Guid Id { get; set; } // NHibernate GUID.comb, NO autoincrement ints!!
public DateTime CDate { get; set; }
public string CUser { get; set; }
public DateTime MDate { get; set; }
public string MUser { get; set; }
public string Street { get; private set; }
public string AdrInfo1 { get; private set; }
public string AdrInfo2 { get; private set; }
public string ZipCode { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
}
To use this with ServiceStack I need to support the following:
CRUD functionality
Filter / search functionality
So my 'Address service' should have the following methods:
GetAddresses (ALL, ById, ByZip, ByCountry, ByCity)
AddAddress (Complete AddressDTO without Id. CDate, CUser are filled automatically without user input)
UpdateAddress (Complete AddressDTO without CUser and CDate, MDate and MUser filled automatically without user input)
DeleteAddress (Just the Id)
For me it is pretty clear, that all Requests return either a single AddressDto or a List<AddressDto> as ResponseDTO except for the delete which should just return a status object.
But how to define all those RequestDTO's? Do I really have to define one DTO for EACH scenario?? In the books I only saw samples like:
[Route("/addresses", "GET")]
public class GetAddresses : IReturn<AddressesResponse> { }
[Route("/addresses/{Id}", "GET")]
public class GetAddressById : IReturn<AddressResponse>
{
public Guid Id { get; set; }
}
[Route("/addresses/{City}", "GET")]
public class GetAddressByCity : IReturn<AddressResponse>
{
public string City { get; set; }
}
// .... etc.
This is a lot of boilerplate code and remembers me a lot of old IDL compilers I used in C++ and CORBA.....
Especially for Create and Update I should be able to 'share' one DTO or even better reuse my existing DTO... For delete there is probably not much choice....
And then the filters. I have other DTOs with a lot more properties. A function approach like used in WCF, RPC etc is hell to code...
In my repositories I pass an entire DTO and use a predicate builder class which composes the LINQ where clause depending on the properties filled. This looks something like this:
List<AddressDto> addresses;
Expression<Func<Address, bool>> filter = PredicateBuilder.True<Address>();
if (!string.IsNullOrEmpty(address.Zip))
filter = filter.And(s => s.Zip == address.Zip);
// .... etc check all properties and dynamically build the filter
addresses = NhSession.Query<Address>()
.Where(filter)
.Select(a => new AddressDto
{
Id = a.Id,
CDate = a.CDate,
//.... etc
}).ToList();
Is there anything similar I could do with my RequestDTO and how should the routing be defined?
A lot of questions raised here have been covered in existing linked answers below. The Request / Response DTOs are what you use to define your Service Contract, i.e. instead of using RPC method signatures, you define your contract with messages that your Service accepts (Request DTO) and returns (Response DTO). This previous example also walks through guidelines on designing HTTP APIs with ServicesStack.
Use of well-defined DTOs have a very important role in Services:
You want to ensure all types your Services return are in DTOs since this, along with the base url of where your Services are hosted is all that's required for your Service Consumers to know in order to consume your Services. Which they can use with any of the .NET Service Clients to get an end-to-end Typed API without code-gen, tooling or any other artificial machinery.
DTOs are what defines your Services contract, keeping them isolated from any Server implementation is how your Service is able to encapsulate its capabilities (which can be of unbounded complexity) and make them available behind a remote facade. It separates what your Service provides from the complexity in how it realizes it. It defines the API for your Service and tells Service Consumers the minimum info they need to know to discover what functionality your Services provide and how to consume them (maintaining a similar role to Header files in C/C++ source code). Well-defined Service contracts decoupled from implementation, enforces interoperability ensuring that your Services don't mandate specific client implementations, ensuring they can be consumed by any HTTP Client on any platform. DTOs also define the shape and structure of your Services wire-format, ensuring they can be cleanly deserialized into native data structures, eliminating the effort in manually parsing Service Responses.
Auto Queryable Services
If you're doing a lot of data driven Services I recommend taking a look at AutoQuery which lets you define fully queryable Services without an implementation using just your Services Request DTO definition.

How can I bind multiple 'Keys' to a single property on a Service Stack Request DTO

I have a DTO that goes something like this:
public class Request {
public id ASpecificIdentifier { get; set; }
public string PreciseDescription { get; set; }
public string FirstPartOfSomeonesName { get; set; }
}
Whilst I'm happy accepting this as the official 'Input', I would also like to be able to bind them to multiple keys. The reason for this will be serialized to a client in an encrypted JSON object, so I would like to keep the length down.
For example they should also be able to pass:
{
"Id":1,
"Desc":"My Issue",
"Name":"Bob"
}
How can I achieve this? I have looked around at the Attributes supplied but non seem to be able to allow this behaviour?
You could create multiple DTOs for each scenario you allow (set of named parameters). Then in your service you would have to handle each DTO and translate them a common DTO to take action.
Or Another way would be to have a DTO that takes a generic key/value parameter. This will make your DTOs very flexible but you will lose some of the advantages of strong typing.
For Example:
public class Request {
Dictionary<string,string> Properties { get; set; }
}

Resources