ServiceStack IReturn - c#

I am looking at the new api that came out 2 weeks ago. It seems like
ReqDTO : IReturn<List<ResDTO>> { //... }
The "IReturn" bit seems to be optional? The DTOs in RazorRockstars demo project works without it.

This is a new addition in ServiceStack's New API which allows you to document the expected Response Type that the Request DTO will return, e.g. with
ReqDTO : IReturn<List<ResDTO>> { ... }
Which lets you call using any of the C# Service Clients with:
List<ResDTO> response = client.Get(new ReqDto());
If you didn't have the IReturn marker your client call would have to look like:
List<ResDTO> response = client.Get<List<ResDTO>>(new ReqDto());
Which is something the client/consumer of your service needs to know about. If you had the marker on the DTO the response type is already known.
The IReturn<> marker is also used to determine the Response DTO that's used in the HTTP Responses in ServiceStack's /metadata pages.

As far as I know, this is just a convenient way of defining your request/response DTOs.
You're free to use it, or not.

In the case where you define your DTOs in a portable class library, you won't be able to use IReturn. Perhaps IReturn should be defined in a PCL in ServiceStack. Just a thought.

Related

Grpc code first JSON transcoding in .Net 7

I am trying to add grpc json transcoding to my grpc code first project but can't seem to figure out on how to add that "option"
In the Microsoft demo the set the json transcoding as follows in the protobuf file
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
In code first you have the following as an example as your protobuf but I can't seem to figure out how to add that option for the json transcoding
[ServiceContract]
public interface IReportService
{
[OperationContract]
Task<ReportListResponse> Getreports(ProtoBuf.Grpc.CallContext context = default);
}
Currently, no: not supported. It is something we can consider as a future investment, but: everything is time :/
There is nothing stopping you from defining your services in proto files and then transcoding them but yeah that's a giant pain the arse if you have request or response schemas that are not very lightweight.

Serenity MVC Framework use Web Service

I love the Serenity MVC framework and would like to use it as much as possible. I am returning data from a web service and would like to implement the framework using the return List<>. I know it is built on the Entity Frame work, but is it possible to have an override where we can get the data from a web service rather than a database?
You should derive your request and response classes from ServiceRequest and ServiceResponse then you can accept any parameter type inside it, e.g:
MyResponse : ServiceResponse
{
Result: List< Something >
}

What RPC technology can I use to call a compiled assembly (rather than my own class) in C#?

I want to access a .NET compiled assembly through RPC (the calling code is Python but that is not really relevant).
The assembly represents an API to a running third-party application (Autodesk AutoCAD, for example). It contains several namespaces which contain static classes which contain API objects. I need to access all kinds of stuff in that object hierarchy: properties, objects, methods and, perhaps most complex, transactions that use IDisposable interface (that essentially means that state, i.e. objects storage, should be maintained between RPC calls).
Rather than continuing to develop my own solution (which uses ZeroMQ messaging and reflection-based call dispatch), I wonder what RPC technology would suit my needs.
I looked into basic examples of popular libraries that implement JSON-RPC and SOAP. I see that these libraries demand that you inherit your callable class from their base classes and put attributes into class declaration, for example
[SoapMethod("RequestResponseMethod")]
in order for RPC to work. Obviously, I cannot do that in the case of an external pre-compiled assembly.
I would like to know if JSONRPC or SOAP are indeed the wrong choice for the task that I described or there actually is a way to make RPC work with an external assembly that I don't know about.
Any guidance, comments or basic advice would be much appreciated since I have no experience using any of the existing RPC technologies.
If you are talking about JSON / SOAP I guess you are using HTTP, which is stateless => you need to supply some kind of "state variable". This can be done via e.g. a cookie or like in my examle:
To access your external API create a "wrapper service" (using WCF or "old-school web-services"):
public class MyApiAccess : IMyApiService
{
private static Dictionary<int, MyAPI> apiInstances = new Dictionary<int, MyAPI>();
public int StartSession()
{
var api = new MyAPI();
int id = api.Id; // or some other way to get an unique id
apiInstances.Add(id, api);
return id;
}
public void EndSession(int sessionId)
{
// ensure "sessionId" is valid
var api = apiInstances[sessionId];
api.Dispose();
apiInstances.Remove(api);
}
public MyType MyMethod(myParameter param)
{
// ensure "sessionId" is valid
var api = apiInstances[sessionId];
return api.MyMethod(param);
}
}
This should give you a starting point how such a service could be implemented.

Replacing legacy system & creating new server code using ServiceStack + custom serialization

We have a legacy server code that we want to abandon and develop new one using ServiceStack. Existing clients are not written in .Net. We don't plan to use .Net on the client side at all.
Data between client and server is being exchanged using XML and JSON - at the moment JSON is only used as a return format for the response (just for some of the services available). XML format was defined when the first version of the server solution was created couple of years ago. We don't want to change it.
How do we use ServiceStack to build new RESTful webservices, that will serialize and deserialize data to a format that was designed in the past (please note, that clients will not be written in C#/.Net). We need to contol both: serialization & deserialization. Is that possible to use DTOs and still have control on how are these objects serialized / deserialized?
Adding custom logic via Request / Response Filters
See Request and response filters to see how to add custom logic before and after your service is called. It's best to add these filters via the Request / Response FilterAttributes as it allows you mark only the services that need these filters applied.
The problem with the Request Filter is it happens after the deserialization into the request DTO which is too late to add custom de-serialization logic. To get around this you can register a custom Request binder in your AppHost with:
base.RegisterRequestBinder<MyRequest>(httpReq => ... requestDto);
This gives you access to the IHttpRequest object and lets you add the custom deserialization logic yourself. The other option is to tell ServiceStack to not attempt to deserialize the request itself and instead inject the HttpRequest InputStream so you can deserialize the request yourself:
public class Hello : IRequiresRequestStream {
Stream RequestStream { get; set; }
}
Both these examples are explained on ServiceStack's Serialization and De-Serialization wiki page.
Registering your own Custom Media Type
Another option to be able to return strong-typed DTOs but change the output for certain requests can be done by adding a new custom media type as explained in the Northwind VCard Custom media type example, e.g:
public static void Register(IAppHost appHost)
{
appHost.ContentTypeFilters.Register( "text/x-vcard", SerializeToStream, DeserializeFromStream);
}
...
public static void SerializeToStream(IRequestContext requestContext, object response, Stream stream)
{
var customerDetailsResponse = response as CustomerDetailsResponse;
using (var sw = new StreamWriter(stream))
{
if (customerDetailsResponse != null)
{
WriteCustomer(sw, customerDetailsResponse.Customer);
}
var customers = response as CustomersResponse;
if (customers != null)
{
customers.Customers.ForEach(x => WriteCustomer(sw, x));
}
}
}
This is a good option if you can mount the custom XML responses under a different Content Type, e.g. application/v-xml so it doesn't conflict with the existing XML format/endpoint. Using the ContentType above your HTTP Client can call this custom implementation with ?format=v-xml or using the HTTP Header: Accept: application/v-xml.
If you want to override the built-in XML ContentType you still can but I recommend falling back to the original XmlSerializer implementation for the SerializeStream and DeserializeStream methods if it's not one of the legacy formats you have to support.
By-pass ServiceStack and execute using your own Custom IHttpHandler
Another option is to by-pass ServiceStack completely and instead process the request in your own custom IHttpRequest handler by registering it in ServiceStack's config in your AppHost:
SetConfig(new EndpointHostConfig {
RawHttpHandlers = {
httpReq => return IsLegacyMatch(httpReq) ? new LegacyXmlHandler() : null
}
});
Returning non-null (i.e. any handler) by-passes ServiceStack.

how to use your same Domain entities throug a .Net webservice?

if you have an entity which is reference in the client and a webservice like this
public class Post
{
public int ID {get; set;}
string Data {get; set;}
}
public class MyService: System.Web.Services.WebService
{
[WebMethod]
public int Write (Post post)
{
//Do stuff
}
}
on the client in order to use the entity you to instantiate from the proxy class
public void ClientMethod()
{
var post = new proxyclass.Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
how can i use my domain entity to call the webservice?
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
Basically, you can't - with regular web-services, at least... the proxy class is completely separate. However, the above is possible with WCF, where you don't actually need proxy classes at all (however, for SOA purity it is a good idea to use them).
You could use reflection (etc) to copy the properties between your domain entities and the proxies, but it is quite hard to get this 100% right (although xml serialization should work [in theory] as an intermediate language).
So; if you want to use assembly sharing; consider using WCF, which supports this ;-p
To get hold of a service without using a proxy layer, you can do tricks like:
public class WcfClient<T> : ClientBase<T> where T : class
{
public T Service { get { return base.Channel; } }
}
(this will access the default configuration from the app.config; for more control you need to add a few constructor overloads matching to the base constructor overloads)
Then:
interface IFoo {void Bar();}
...
using(WcfClient<IFoo> client = new WcfClient<IFoo>()) {
client.Service.Bar();
}
I suspect that one of these might answer your qestion. The common theme is wsdl.exe /sharetypes and svcutil /reference.
Managing 2 web references with shared class dependency in a .NET project
Force .NET webservice to use local object class, not proxy class
.Net Consuming Web Service: Identical types in two different services
How to get a webserice to serialize/deserialize the same type in .net
.NET SOAP Common types
wsdl.exe /sharetypes
You should use WCF for new development whenever possible.
However, you should reconsider your reasons for wanting to use your domain class on the client. It does violate the principles of SOA by exposing to the client some details of the implementation of the service. Why should the client know anything about your entity classes, beyond the data that they contain?
For instance, your entity classes may contain methods to save the entity to the database. Why does your client need access to that method?
Also, one of the principals of SOA is to interoperate with different platforms. As soon as you require your client to use your (.NET) entity, you prevent a Java or PHP client from being written to use your service.
You may have good enough reasons to overcome such objections, but I recommend that you think it through and make sure your reasons are good enough.
For cases like this you're better to use json for sending and receiving data to and from web service.
Newtonsoft.json is the best json serializer for .Net. so you should change your Write method like below:
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(JsonConvert.SerializeObject(post))
}

Categories

Resources