ServiceStack AutoQuery, Multiple IJoin - servicestack

In my example I have the following database structure. Order has many OrderLine, which has one Product.
I am trying to return the following DTO:
public class OrderLineDto {
public int Id { get; set; }
public int Quantity { get; set; }
public string OrderType { get; set; }
public string ProductName { get; set; }
}
This should be possible by use of the following Query Route:
[Route("/orderlines")]
public class FindOrderLines : QueryBase<OrderLine, OrderLineDto>,
IJoin<OrderLine, Order>,
IJoin<OrderLine, Product>
{ }
What I am trying to do here is join OrderLine in both directions to bring in Type from Order, and Name from Product and return it in an OrderLineDto.
I am able to do these things individually by only using one IJoin, however AutoQuery appears only to use the first IJoin interface declaration, and does not perform the second join.
If I attempt to do a join like this: IJoin<OrderLine, Order, Product>
I get the following exception: Could not infer relationship between Order and Product
Is it possible to achieve what I am trying to do here with auto query or should I go back to writing standard REST services, abandoning AutoQuery?

I have submitted a pull request to ServiceStack which will now allow this behavior.
https://github.com/ServiceStack/ServiceStack/pull/955

Related

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; }
}

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.

ORMLite SQL Server Update

I have a table called PODetail with a primary Key of POno and ItemCode and I have the following:
[Route("/podetail/{POno}/{ItemCode}")]
public class UpdatePODetail : IReturn<PODetail> {
public string POno { get; set; }
public string ItemCode { get; set; }
public int ? QtyPend { get; set; }
public decimal ? NewPrice { get; set; }
public bool ? BackOrder { get; set; }
public string ActionCode { get; set; }
public bool ? OpenOrder { get; set; }
}
public class PODetailService : Service {
public object Any(UpdatePODetail request) {
var podetail = Db.SingleFmt<PODetail>("ItemCode = {0} AND POno = {1}", request.ItemCode, request.POno);
// var cap = new CaptureSqlFilter();
try {
Db.Update(podetail);
} catch {
// var sql = string.Join(";\n\n", cap.SqlStatements.ToArray());
}
:
:
try {
Db.Update(podetail);
} catch (Exception ex) {
string error = ex.Message;
}
return podetail;
}
}
I added the Db.Update call at the top just to check to see if there was some issue changing a column, but I get
Violation of PRIMARY KEY constraint 'aaaaaPoDetail_PK'. Cannot insert
duplicate key in object 'dbo.PODetail'.
So then I added the cap = line to see the SQL code which returns
UPDATE "PODetail" SET "NewItemCode"=#NewItemCode, "POno"=#POno, "Vendor"=#Vendor, "ActionCode"=#ActionCode, "Price"=#Price, "NewPrice"=#NewPrice, "CostPrice"=#CostPrice, "QtyOrd"=#QtyOrd, "QtyRcv"=#QtyRcv, "QtySPO"=#QtySPO, "QtyPend"=#QtyPend, "BackOrder"=#BackOrder, "OpenOrder"=#OpenOrder, "OrderDate"=#OrderDate, "InvoiceNo"=#InvoiceNo, "InvoiceVendor"=#InvoiceVendor, "InvoiceDate"=#InvoiceDate, "InvoiceDiscount"=#InvoiceDiscount, "QtyCancel"=#QtyCancel, "Qtylabels"=#Qtylabels, "REOVendor"=#REOVendor, "CurrentRcvQty"=#CurrentRcvQty, "SOPickQty"=#SOPickQty, "SOItem"=#SOItem, "QtyOther"=#QtyOther, "BackOrderCode"=#BackOrderCode WHERE "ItemCode"=#ItemCode
And then it runs fine uncommented -- no exceptions .. if I remove it it gets the Primary Key error
What is the deal -- why do I need that CaptureSqlFilter call -- or what I do I need to change so that it knows both PoNo and ItemCode are primary Keys or the update needs to say WHERE "ItemCode"=#ItemCode AND "POno"=#PONo? It almost seems as if it is trying to do an INSERT vs an UPDATE without the CaptureSqlFilter
Update 1
The documentation said :
Limitations For simplicity, and to be able to have the same POCO class
persisted in db4o, memcached, redis or on the filesystem (i.e.
providers included in ServiceStack), each model must have a single
primary key, by convention OrmLite expects it to be Id although you
use [Alias("DbFieldName")] attribute it map it to a column with a
different name or use the [PrimaryKey] attribute to tell OrmLite to
use a different property for the primary key.
You can still SELECT from these tables, you will just be unable to
make use of APIs that rely on it, e.g. Update or Delete where the
filter is implied (i.e. not specified), all the APIs that end with
ById, etc.
Workaround single Primary Key limitation
A potential workaround to support tables with multiple primary keys is
to create an auto generated Id property that returns a unique value
based on all the primary key fields,
So I tried to add this
public class PODetail {
public string Id { get { return this.ItemCode + "/" + this.POno; } }
public string ItemCode { get; set; }
public string NewItemCode { get; set; }
public string POno { get; set; }
:
}
But when it went to execute :
Db.SingleFmt<PODetail>
It error out with ID not a valid column or column not found or something like that
So I then tried
public class PODetail {
//public string Id { get { return this.ItemCode + "/" + this.POno; } }
[PrimaryKey]
public string ItemCode { get; set; }
public string NewItemCode { get; set; }
[PrimaryKey]
public string POno { get; set; }
:
}
and it worked on the Db.SingleFmt ... and the Db.Update
So then I added back in the CaptureSqlFilter to see what the query looked like and I got
UPDATE "PODetail" SET "NewItemCode"=#NewItemCode, "Vendor"=#Vendor, "ActionCode"=#ActionCode, "Price"=#Price, "NewPrice"=#NewPrice, "CostPrice"=#CostPrice, "QtyOrd"=#QtyOrd, "QtyRcv"=#QtyRcv, "QtySPO"=#QtySPO, "QtyPend"=#QtyPend, "BackOrder"=#BackOrder, "OpenOrder"=#OpenOrder, "OrderDate"=#OrderDate, "InvoiceNo"=#InvoiceNo, "InvoiceVendor"=#InvoiceVendor, "InvoiceDate"=#InvoiceDate, "InvoiceDiscount"=#InvoiceDiscount, "QtyCancel"=#QtyCancel, "Qtylabels"=#Qtylabels, "REOVendor"=#REOVendor, "CurrentRcvQty"=#CurrentRcvQty, "SOPickQty"=#SOPickQty, "SOItem"=#SOItem, "QtyOther"=#QtyOther, "BackOrderCode"=#BackOrderCode WHERE "ItemCode"=#ItemCode AND "POno"=#POno
Which is what I wanted in the first place.
It works but what is the deal can you have the [PrimaryKey] attribute multiple times (it appears so) and also then why didn't the autogenerated Id work? Just wondering if I am missing something or not understanding the documentation correctly.
Oh and sorry for posting in the comments!
what I do I need to change so that it knows both PoNo and ItemCode are
primary Keys
OrmLite's primary limitation is that each Table has a single primary Key.
Also you can use the built-in Profiling or debug logging to view the generated SQL without needing to change code to use CaptureSqlFilter.
I'd also recommend that you don't use the Request DTO for anything other than defining your Service with. You can use the built-in AutoMapping to easily use it to populate your data model.

categorize ServiceStack methods

Imagine I have two "areas" in my API, inventory and orders. I can quite easily group all methods related to inventory into "/inventory/" and to orders "/orders/" routes.
However, when I go to the root page of API where all methods are shown (IndexOperations.html) all methods are mixed together into one big list.
Is there any way to group methods from different areas on that list? For example show something like this on the operations index page.
Inventory
Method1
Method2
Orders
Method1
Method2
Group your operations:
If you group your DTOs into a static class as shown below, then ordering will be taken care of automatically assuming you want the groups alphabetically.
public static class UserOperations
{
[Route("/Users","POST")]
public class CreateUserRequest
{
public string Name { get; set; }
public int Age { get; set; }
}
...
}
public static class DuckOperations
{
[Route("/Ducks","POST")]
public class CreateDuckRequest
{
public string Name { get; set; }
public int Age { get; set; }
}
...
}
Alternatively specify the sort:
The ServiceStack MetadataFeature in v4.09+ provides access to the IndexPageFilter which lets you specify specify the Sort function that is applied to the index pages' OperationNames, where the OperationName is the full type name of the DTO.
var metadata = Plugins.First(x => x is MetadataFeature) as MetadataFeature;
// This is the default sort, replace with one that groups
metadata.IndexPageFilter = (page) => page.OperationNames.Sort((a,b) => b.CompareTo(a));
I hope this helps.

Including a base member doesn't seem to work in Entity Framework 5

here are my entities:
public abstract class ResourceBase
{
[Key]
int Id { get; set; }
[ForeignKey("Resource")]
public Guid ResourceId { get; set; }
public virtual Resource Resource { get; set; }
}
public class Resource
{
[Key]
public Guid Id { get; set; }
public string Type { get; set; }
}
public class Message : ResourceBase
{
[MaxLength(300)]
public string Text { get; set; }
}
And then my query is something like this:
var msgs = messages.Where(x=>x.Id == someRangeOfIds).Include(m=>m.Resource).Select(x => new
{
message = x,
replyCount = msgs.Count(msg => msg.Id = magicNumber)
});
I am running this with proxy creation disabled, and the result is all the messages BUT with all the Resource properties as NULL. I checked the database and the Resources with matching Guids are there.
I drastically simplified my real life scenario for illustration purposes, but I think you'll find you can reproduce the issue with just this.
Entity Framework 5 handles inherited properties well (by flattening the inheritence tree and including all the properties as columns for the entity table).
The reason this query didn't work was due to the projection after the include. Unfortunately, the include statement only really works when you are returning entities. Although, I did see mention of a solution which is tricky and involves invoking the "include" after the shape of the return data is specified... If anyone has more information on this please reply.
The solution I came up with was to just rephrase the query so I get all messages in one query, and then in another trip to the database another query that gets all the reply counts.
2 round trips when it really should only be 1.

Resources