What are my options in ServiceStack to assign a unique ID to each request? - api

I'm building an API with ServiceStack. I'd like each request to have a unique ID so that I can trace it through the system (which is distributed).
I have my contracts assembly containing my API's DTOs, and so I thought the natural place would be to make each Request derive from a base class that had a sealed protected parameterless constructor that assigned a new ID (probably a GUID is fine).
However, it'll be possible to use my API via the clients without necessarily using the contract DTOs assembly - naked, if you will. At that point, the clients can assign whatever IDs they like (since the property will be a string to be accomodating, and I want ID assignment to be quick).
So, this leads me to think that the service should assign request IDs when the requests arrive at the system. So - I'm currently thinking that the best thing to do is have an ID property on each request DTO that is validated to be empty by the API - clients cannot set it. Then, a before-everything filter to assign a value to the DTO property.
Is that sensible?
Is there a more elegant way to do it (that still works against naked clients?)?

Using a global request filter would work, you can do something like:
public class IRequiresUniqueId
{
public Guid UniqueId { get; set; }
}
And then mark all request DTOs you would like to have a Unique Id by implementing the above interface:
public MyRequest : IRequiresUniqueId
{
public Guid UniqueId { get; set; }
}
Then you can use a Global Request Filter to set all request DTOs that have them:
this.RequestFilters.Add((httpReq, httpResp, requestDto) =>
{
var requiresUniqueId = requestDto as IRequiresUniqueId;
requiresUniqueId.UniqueId = Guid.NewGuid();
});

Related

What is the recommended way to do partial updates with PATCH in ServiceStack?

I am building a RESTful API using the ServiceStack framework. A lot of the resources that I need to update are quite big, with up to 40 attributes per class, so I would like to do partial updates instead of replacing the entire resource. Often the client will only need to update one or two attributes out of the 40, so I would like to just send a JSON body consisting of the few attributes.
Since all combinations of attributes are possible, it is not feasible to make an "Update" class per class as suggested here: https://github.com/ServiceStack/ServiceStack/wiki/New-Api#patch-request-example
In the Microsoft ASP.NET WebAPI OData package there is a Delta class that takes a subset of a class and updates the resource based on this subset (http://www.strathweb.com/2013/01/easy-asp-net-web-api-resource-updates-with-delta/). This is the functionality I would like to have, as I will be having quite a few classes so a generic method would be best.
Basically, if I have a class
public class MyClass {
public int a { get; set; }
public int b { get; set; }
...
public int z { get; set; }
}
I would like to update a resource of MyClass with a PATCH request with body
{"a":42,"c":42}
Is there a standard or recommended way to accomplish this with ServiceStack?
Declare any scalar values in your DTO as nullable. This will allow you to determine which fields were actually sent in the request:
public class MyClass {
public int? a { get; set; }
public int? b { get; set; }
public int? c { get; set; }
// etc.
// object-type properties are already nullable of course
public string MyString { get; set; }
}
Now if a client sends a partial request, like so:
{ "a": 1, "b": 0 }
You'll be able to determine which properties were actually sent when inspecting your DTO:
myClass.a == 1
myClass.b == 0
myClass.c == null
myClass.MyString == null
etc.
Set up a PATCH route for your DTO and implement a Patch method in your service:
public object Patch(MyClass request)
{
var existing = GetMyClassObjectFromDatabase();
existing.PopulateWithNonDefaultValues(request);
SaveToDatabase(existing);
...
}
PopulateWithNonDefaultValues is key here. It will copy values from your request object onto the database entity, but will only copy properties that are not the default values. Thus, if a value is null, it won't copy it, because the client didn't send a value for it. Notice that it will copy an integer value of zero though, because we made it a nullable int, and the default value for a nullable int is considered by this method to be null, not zero. Declaring your DTO properties as nullable shouldn't cause much of a hassle in the rest of your code.
Note that this approach works easily with JSON. If you need to support XML requests/responses, you may need need to do some additional work with DataContract/DataMember attributes to insure that nulls are handled correctly.
While esker's response is fine I would like to add that it might not be enough for nullable fields - since you don't know if the deserializer or the user have created that null field.
One approach would be to peek at the raw request.
A different approach is to ask the user to provide additional request (querystring) parameter to clearly specify which fields to patch.
Something like: patch_fields=name,description,field3
The bonus of that approach is that the end user has more control over the patching and is not overriding a value by mistake (because he used the original entity and forgot to clear some fields)

silverlight domain service don't allow return a generic object

I have a domain service running smooth, some expose functions that return generic lists of defined entity, but for some reason, I had add some common information so I created a generic object to wrap the collection with the extra information that I need return.
but when after made the change and try use the service in the client, the function don't show up in the context, I already search about it and what I found was attributes for generic IQueryable
my wrap class
public class Wrap<T>
{
public String commonProperty { get; set; }
public String anotherCommonProperty { get; set; }
public List<T> items { get; set; }
}
in my service domain
public Wrap<SomeClass> GetAll()
{
Wrap<SomeClass> myObject = new Wrap<SomeClass>();
myObject.items = new List<SomeClass>();
myObject.commonProperty = "some info";
myObject.anotherCommonProperty = "some info";
return myObject;
}
Maybe adding the [KnownType(typeof(SomeClass))] attribute in the Wrap<T> class, the problem is that you need to include one KnowType attribute for every class in your domain (this is because you are making a polymorphic service).
And adding the [ServiceKnownType(typeof(SomeClass))] in the GetAll method in the service (this is for wcf services I don't know if is valid for domain services).
WCF RIA domain services does not support generic entity types. IEnumerable<T> and IQueryable<T> are special cases.
Your method was ignored because it did not match supported method type.
Before changes GetAll was recognized as Query method. You can force that by adding attribute.
[Query]
public Wrap<SomeClass> GetAll()
Now it does not dissapear silently. But generates compile time error instead:
Type 'Wrap`1' is not a valid entity type. Entity types cannot be
generic.

Can't serialize nested nHibernate entity for WCF web service

I'm trying to use nHibernate, Spring and WCF together. I've got an Order object, and that contains a Customer object.
I can call a WCF method findOrder on my service, and providing the Order's Customer field does not have a DataMember annotation, the Web Service returns the Order I wanted. It does not contain the Customer details though, as expected.
But when I try to include the Customer as well, the WebService fails, and looking in the WCF trace logs, I can see this error:
System.Runtime.Serialization.SerializationException:
Type 'DecoratorAopProxy_95d4cb390f7a48b28eb6d7404306a23d' with data contract name
'DecoratorAopProxy_95d4cb390f7a48b28eb6d7404306a23d:http://schemas.datacontract.org/2004/07/'
is not expected. Consider using a DataContractResolver or add any types not known statically to
the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the
list of known types passed to DataContractSerializer
Pretty sure this is because the Customer contains extra nHibernate details, but I don't understand why WCF would be happy to send the Order, but not the Customer.
Can anyone help me understand?
Order object
[DataContract]
[KnownType(typeof(Customer))]
public class Order
{
// Standard properties
[DataMember]
public virtual int Id { get; set; }
public virtual Enums.OrderStatus Status { get; set; }
[DataMember]
[StringLength(20, ErrorMessage = "Order name must not be more than 20 characters long")]
public virtual string Name { get; set; }
[DataMember]
public virtual Customer Customer { get; set; }
[DataContract]
...
}
Customer object
public class Customer
{
public virtual int CustomerId { get; set; }
[DataMember]
private string name = "";
...
}
You should use a data transfer objects (DTO) to get your data over the wire. This is good practice anyway as you do not want to let your domain model leak into (and out of) the boundaries of your application.
Think about things like every change in your domain model results in a change of your data contract, resulting in a new wsdl, resulting in a change on the client. In addition you are telling the consumer of your service too many insights of your aplication.
Despite all this architectural bla bla. NHibernate uses proxies to enable lazy loading, those proxies are of another type than you serializer expects. You can disable lazy loading for your domain to get the application working. This is imho a bad idea.
<class name="Customer" table="tzCustomer" lazy="false" >

Populating association properties in entities from service call

Say I have a common pattern with a Customer object and a SalesOrder object. I have corresponding SalesOrderContract and CustomerContract objects that are similar, flatter objects used to serialize through a web service
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public Address ShippingAddress { get; set; }
//more fields...
}
public class Order
{
public int OrderId { get; set; }
public Customer Customer { get; set;
// etc
}
And my sales order contract looks like this
public class OrderContract
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
}
public class OrderTranslator
{
public static Order ToOrder(OrderContract contract)
{
return new Order { OrderId = contract.OrderId };
// just translate customer id or populate entire Customer object
}
}
I have a layer inbetween the service layer and business object layer that translates between the two. My question is this...do I populate the Order.Customer object on the other end since the Order table just needs the customer id. I don't carry the entire customer object in the OrderContract because it's not necessary and too heavy. But, as part of saving it, I have to validate that it's indeed a valid customer. I can do a few things
Populate the Order.Customer object completely based on the CustomerId when I translate between contract and entity.. This would require calling the CustomerRepository in a helper class that translates between entities and contracts. Doesn't feel right to me. Translator should really just be data mapping.
Create a domain service for each group of operations that performs the validation needed without populating the Order.Customer. This service would pull the Customer object based on Order.CustomerId and check to see if it's valid. Not sure on this because a sales order should be able to validate itself, but it's also not explicitly dealing with Orders as it also deals with Customers so maybe a domain service?
Create a seperate property Order.CustomerId and lazy load the customer object based on this.
Populate Order.Customer in from a factory class. Right now my factory classes are just for loading from database. I'm not really loading from datacontracts, but maybe it makes sense?
So the question is two part...if you have association properties in your enties that will be required to tell if something is completely valid before saving, do you just populate them? If you do, where you do actually do that because the contract/entity translator feels wrong?
The bottom line is that I need to be able to do something like
if (order.Customer == null || !order.Customer.IsActive)
{
//do something
}
The question is where does it make sense to do this? In reality my Order object has a lot of child entities required for validation and I don't want things to become bloated. This is why I'm considering making domain services to encapsulate validation since it's such a huge operation in my particular case (several hundred weird rules). But I also don't want to remove all logic making my objects just properties. Finding the balance is tough.
Hope that makes sense. If more background is required, let me know.
You have a couple of things going on here. I think part of the issue is mainly how you appear to have arranged your Translator class. Remember, for an entity, the whole concept is based on instance identity. So a Translator for an entity should not return a new object, it should return the correct instance of the object. That typically means you have to supply it with that instance in the first place.
It is perhaps useful to think in terms of updates vs creating a new object.
For an update the way I would structure this operation is as follows: I would have the web service that the application calls to get and return the contract objects. This web service calls both repositories and Translators to do it's work. The validation stays on the domain object.
In code an update would look something like the following.
Web Service:
[WebService]
public class OrderService
{
[WebMethod]
public void UpdateOrder(OrderContract orderContract)
{
OrderRepository orderRepository = new OrderRepository(_session);
// The key point here is we get the actual order itself
// and so Customer and all other objects are already either populated
// or available for lazy loading.
Order order = orderRepository.GetOrderByOrderContract(orderContract);
// The translator uses the OrderContract to update attribute fields on
// the actual Order instance we need.
OrderTranslator.OrderContractToOrder(ref order, orderContract);
// We now have the specific order instance with any properties updated
// so we can validate and then persist.
if (order.Validate())
{
orderRepository.Update(order);
}
else
{
// Whatever
}
}
}
Translator:
public static class OrderTranslator
{
public static void OrderContractToOrder(ref Order order, OrderContract orderContract)
{
// Here we update properties on the actual order instance passed in
// instead of creating a new Order instance.
order.SetSomeProperty(orderContract.SomeProperty);
// ... etc.
}
}
The key concept here is because we have an entity, we are getting the actual Order, the instance of the entity, and then using the translator to update attributes instead of creating a new Order instance. Because we are getting the original Order, not creating a new instance, presumably we can have all the associations either populated or populated by lazy load. We do not have to recreate any associations from an OrderContract so the issue goes away.
I think the other part of the issue may be your understanding of how a factory is designed. It is true that for entities a Factory may not set all the possible attributes - the method could become hopelessly complex if it did.
But what a factory is supposed to do is create all the associations for a new object so that the new object returned is in a valid state in terms of being a full and valid aggregate. Then the caller can set all the other various and sundry "simple" attributes.
Anytime you have a Factory you have to make decisions about what parameters to pass in. Maybe in this case the web service gets the actual Customer and passes it to the factory as a parameter. Or Maybe the web service passes in an Id and the factory is responsible for getting the actual Customer instance. It will vary by specific situation but in any case, however it gets the other objects required, a factory should return at minimum a fully populated object in terms of it's graph, i.e all relationships should be present and traversible.
In code a possible example of new Order creation might be:
[WebService]
public class OrderService
{
[WebMethod]
public void SaveNewOrder(OrderContract orderContract)
{
// Lets assume in this case our Factory has a list of all Customers
// so given an Id it can create the association.
Order order = OrderFactory.CreateNewOrder(orderContract.CustomerId);
// Once again we get the actual order itself, albeit it is new,
// and so Customer and all other objects are already either populated
// by the factory create method and/or are available for lazy loading.
// We can now use the same translator to update all simple attribute fields on
// the new Order instance.
OrderTranslator.OrderContractToOrder(ref order, orderContract);
// We now have the new order instance with all properties populated
// so we can validate and then persist.
if (order.Validate())
{
//Maybe you use a Repository - I use a unit of work but the concept is the same.
orderRepository.Save(order);
}
else
{
//Whatever
}
}
}
So, hope that helps?

Send custom data as object using WCF

In my latest project, I wish to send custom data as an object using WCF. Reason for this is that I won't have to update each client when a new data class is introduced.
However, when I try to send this data, it never arrives at the client side.
To give a short example:
A custom class:
[DataContract]
public class MyData
{
[DataMember]
public string Name { get ;set; }
[DataMember]
public id Value { get; set; }
public MyData(string name, id value)
{
this.Name = name;
this.Value = value;
}
}
When I want to send this to the client, I use:
object obj = new MyData("test",1);
service.SendDataToClient(obj);
The client never receives this event from the service when I send it as object. However, when I send it as MyData instead of object, it works as it should. How can I send this as object?
If you want to send custom data the easy way is using XElement instead of object. Another approach is defining all possible transfered types by ServicKnownTypeAttribute or creating generic resolver (in such case you must share contract assembly between client and service). Check this great article.