Grpc code first JSON transcoding in .Net 7 - c#

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.

Related

Using SoapService Class with WCF web service

I need to create a web service to receive a SOAP request that a customer uses to send out information to various systems, all I have is an example xml payload. I have created a test WCF web service using
https://www.c-sharpcorner.com/article/create-simple-wcf-service-and-host-it-on-console-application/
and was going to just create a class along the lines of
public class WebServiceSOAP : IWebServiceSOAP
{
public string SetProductInfo(string strSOAPRequest)
{
// Parse the xml received, validate etc
string response = ParseSOAPData(strSOAPRequest);
// response depends on if data passes validation or not.
return response;
}
}
and host it in a console App. I then came across SoapService Class during my googling but I am not clear on how this fits in with a normal WCF service as the example here
https://msdn.microsoft.com/en-gb/library/ms819935.aspx
seems to use Microsoft.Web.Services2/3 instead of System.ServiceModel does this mean I can use the same method to set up my webservice as the example I have previously followed? Including the App.config. The example seems for System.ServiceModel seems completely different to the setup of the WCF service I followed. I am clearly missing something. I can't inherit from both the interface and SoapService, plus I would have a function with a [OperationContract] and a [SoapMethod] attribute.
It looks like I could receive the SOAPEnvelope and use SoapEnvelope.GetBodyObject to get the body / payload but I am not clear if it returns xml or if the body still has all the < replaced with < etc Can I just take the result of SoapEnvelope.GetBodyObject and parse the xml?

ServiceStack IReturn

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.

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.

Making of JSON Webservice using C# .NET

I am trying to make JSON webservice in C# .NET. A json string is returning by web method but it contains xml structure like:
<string xmlns="http://tempuri.org/">
{"checkrecord":[{"rollno":"abc2","percentage":40,"attended":12,"missed":34}],"Table1":[]}
</string>
I saw this article before it wasn't much helpful for me.
So my problem is, that json string is not returned in its pure format. I do not want that xml version and xmlns string. I plan to consume the web service on Android later.
Can anyone help me?
Thanks
If you decorate your interface with attributes for request and response format you can get standard WCF to return and interpret proper json.
[WebGet(UriTemplate = "user/{userid}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
The problem is, however, that WCF's innate DataContractJsonSerializer does not always return proper json. Its serialization of dictionaries is problematic at best, since it is serialized as a list of key/value-pairs. To remedy this one has to return Stream from the service methods and do the serialization by hand (using Json.NET or ServiceStack to perform the serialization). In such cases it is probably advisable to use WebAPI, but for some cases regular WCF can be used using the mentioned decorations.
You can try to build your service using the REST Api. You can find the information on REST with WCF at this link
You can download the toolkit for samples on how to build restful wcf services that returns json response.
The WCF Web API is worth learning if you plan to create REST services. It's easily installed via Nuget, or from Codeplex
This is also not a problem when using ServiceStack, i.e. every result you return get's automatically converted in the Response ContentType you want, i.e. this is the full code of a simple web service that can be called via all HTTP VERBS (GET,POST,PUT,DELETE) on all the supported formats (no config required), i.e. JSON, XML, HTML, JSV, CSV, SOAP even by a direct HTML Form x-www-form-urlencoded or QueryString request:
public class Hello {
public string Name { get; set; }
}
public class HelloResponse {
public string Result { get; set; }
}
public class HelloService : IService<Hello> {
public object Execute(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
You can override the response you get with the Accept:application/json HTTP Header or simply adding the ?format=json on the QueryString.
See the ServiceStack's Hello World Example to see a live example the above web services.
Change return in method for
Context.Response.Write(ans);
Context.Response.End();

Dynamic C#.NET Webservice

I am using a class in a C# ASP.NET project to allow a script written in some random scripting language to expose webservice methods dynamically - in other words, the script should be able to expose a method of any name with any signature (as long as it's valid, anyway) to the outside world through this SOAP interface (able to add and remove them at will, without needing a hard code change), and as such I need to be able to create a webservice class in C# while being able to dynamically add and remove methods at runtime.
Now, the best plan I've been able to come up with so far is (runtime) generating C# code to represent the webservice, using System.Reflection.Emit to compile it and then loading the assembly at runtime - all whenever the script adds or removes a method to/from the service (should not happen very often, mind).
Does anyone have a better idea than this?
You can modify WSDL by using SoapExtensionReflector class. From Kirk Evans Blog:
The SoapExtensionReflector is called when your type is being reflected over to provide the WSDL definition for your service. You can leverage this type to intercept the reflection call and modify the WSDL output.
The following example removes the first method out of 2 web service methods:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Multiply(int a, int b)
{
return a * b;
}
}
Create a class inherited from SoapExtensionReflector:
namespace TestWebservice
{
public class MyReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
if (description.PortTypes[0].Operations.Count == 2)
description.PortTypes[0].Operations.RemoveAt(0);
if (description.Messages.Count == 4)
{
description.Messages.RemoveAt(0);
description.Messages.RemoveAt(0);
}
foreach (Binding binding in description.Bindings)
{
if (binding.Operations.Count == 2)
binding.Operations.RemoveAt(0);
}
if (description.Types.Schemas[0].Items.Count == 4)
{
description.Types.Schemas[0].Items.RemoveAt(0);
description.Types.Schemas[0].Items.RemoveAt(0);
}
}
}
}
Add this to configuration/system.web section in web.config:
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
This should give you a starting point to dynamically removing methods from WSDL document. You would also need to throw NotImplementedException from web method if it is disabled.
Finally, you need to disable web service documentation produced by invoking .asmx endpoint without ?WSDL parameter. Set href attribute of wsdlHelpGenerator element to some URL. You can use DefaultWsdlHelpGenerator.aspx as a starting point for your own documentation handler. See question on web service documentation in XML Files, August 2002.
XMLRPC is fairly dead, isn't it?
SOAP implies a WSDL. How do you generate the WSDL dynamically?
You should look into using WCF. I expect you'll be able to take control of the process of generating the WSDL (and other metadata), yet you should also be able to take control of the processing of incoming messages. In particular, you will be able to examine the incoming messages to determine which script to run, what parameters to pass, etc.
You could create a WCF service with an input and output type of xs:any and handle the incoming request as a raw Message. That would allow you to accept any type of data and return any type of data. You would not use data contracts or static types, just a Message in and a Message out.
The problem with this approach is that generating a proxy from the WSDL really does nothing to help the consumer other than provide a wrapper to call the method. Providing data that is acceptable to the method would require hand-rolling data types, etc which is not that hard, it is just not as intuitive as a hard, typed contract.
Does it have to be a SOAP interface? That sounds like it might be more suitable to a route/REST/etc based API. You could do something in ASP.NET MVC (with a custom IController.Execute method that resolves the action to the method) pretty easily (in fact, I'm working on something very similar for some of my own code at the moment).
For example, you might have routes:
http://myserver/myservice/mymethod
that accepts (either in the body or args) the payload (parameters), and returns the result in the response. In non-MVC you should be able to do something similar with a wildcard-mapped generic handler.
Here is a suggestion:
Use WCF.
Create a WSDL from WCF using
information in the following blog
post:
http://www.pluralsight.com/community/blogs/kirillg/archive/2006/06/18/28380.aspx
You can then publish this information
using MEX.
The services are then open for your
clients to down load the meta data
and call the services.

Categories

Resources