Making of JSON Webservice using C# .NET - c#

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();

Related

Does ASP.NET Core Support JSON Web Signatures for RESTful Web APIs?

I have read some excellent tutorials on using JSON Web Tokens with ASP.NET Core to authenticate requests to a REST API, however I can find no documentation on whether the more general JSON Web Signature (rfc7515) is supported for use with REST API Definitions to tamper-protect the contents of requests.
For example, the following Controller allows a simple POST request whereby a JSON serialized 'CreateRequest' object is submitted to the API and handled:
[Produces("application/json")]
[Route("api/WebService")]
public class WebServiceController
{
[HttpPost("CreateRequest")]
public override IActionResult Create([FromBody] CreateRequest request)
{
if (request == null)
{
return BadRequest();
}
else
{
// Do stuff with CreateRequest object ...
return new OkResult();
}
}
}
If I wanted to protect the CreateRequest object from tampering in transit JSON Web Signature seems like a good way to do it, but how do I get the request handler to accept the object when encoded as BASE64 and signed, and preferably only if the signature validates?
I know that integrity protecting the contents could be solved other ways for example by TLS encrypting the connection, but assume for the moment that the request must be made via plain HTTP with the contents in full view. For this reason the similar JSON Web Encryption standard is also unsuitable for my use case.

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?

Return "raw" json in ASP.NET Core 2.0 Web Api

The standard way AFAIK to return data in ASP.NET Core Web Api is by using IActionResult and providing e.g. an OkObject result. This works fine with objects, but what if I have obtained a JSON string somehow, and I just want to return that JSON back to the caller?
e.g.
public IActionResult GetSomeJSON()
{
return Ok("{ \"name\":\"John\", \"age\":31, \"city\":\"New York\" }");
}
What ASP.NET Core does here is, it takes the JSON String, and wraps it into JSON again (e.g. it escapes the JSON)
Returning plain text with [Produces("text/plain")] does work by providing the "RAW" content, but it also sets the content-type of the response to PLAIN instead of JSON. We use [Produces("application/json")] on our Controllers.
How can I return the JSON that I have as a normal JSON content-type without it being escaped?
Note: It doesn't matter how the JSON string was aquired, it could be from a 3rd party service, or there are some special serialization needs so that we want to do custom serialization instead of using the default JSON.NET serializer.
And of course a few minutes after posting the question I stumble upon a solution :)
Just return Content with the content type application/json...
return Content("{ \"name\":\"John\", \"age\":31, \"city\":\"New York\" }", "application/json");
In your action, replace Ok() with the Content() method, which lets you set the content (raw content), content type, and status code of your response: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.contentresult?view=aspnetcore-2.0
This worked for me, where Json() did not:
return new JsonResult(json);

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 send an object to C# WCF service from PHP using SOAP

I'm having trouble sending a custom object thats defined as a datacontract in my WCF web service from PHP. I'm attempting to accomplish this via SOAP.
Here is what the dataContract looks like:
[DataContract]
public class simplyCustomer
{
[DataMember]
public int id;
[DataMember]
public string name;
[DataMember]
public string contact;
[DataMember]
public string street1;
[DataMember]
public string street2;
[DataMember]
public string city;
[DataMember]
...
}
So I have a function that takes simplyCustomer as parameter on WCF service. The php can receive simplyCustomer just fine using another function that returns one. However, if I call the one that accepts it using this code in PHP:
$retVal = $simplyService->__soapCall("addCustomer",array('parameters'=>$params));
The SOAP envelope that this call generates leaves the object NULL causing the WCF service to complain about null reference.
Here is the envelope that is generated:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/"><SOAP-ENV:Body><ns1:addCustomer/></SOAP-ENV:Body></SOAP-ENV:Envelope>
The parameters should be where addCustomer is but there's nothing there.
Any help would be greatly appreciated!
Thanks!
I faced the same issue when building a private project.
My solution was to use T4 to generate service- and datacontract proxies, maybe you find it useful. Message me if you have any questions, the templates are not tested to their full extent.
You find the templates on github, including sample servicecontracts/datacontracts:
https://github.com/schaermu/wcf-phpclient-t4
feel free to fork the project!
cheers
Though this is asked while before, thought to add my input since I came accros the same issue.
Assuming your operation contract look something similar to
[OperationContract]
public <return_type> addCustomer(simplyCustomer parameters);
what you have suggested should work given that $params got all the required values set on initialisation where ever that has done and variable names are exactly similar to data contract.
Few tips going through this though.
1) If you have manage to send the object to the service, Could check the service logs to see what has gone wrong.
2) Just check your constructor to see all the parameters are set.
3) Also good to check that soap client is initialized and consumed properly.
eg : (following is, one of many possibilities)
$client = new Client( $baseUrl, array('soap_version' => SOAP_1_1,));
$result = $client->addCustomer(array("parameters" => $params ));
I had the same kind of problem. Cant see how you built your $params but I solved mine by doing this:
$username = "test";
$password = "test";
$input = array ("composite" => array("Password" => $password, "UserName" => $username));
$result=$client->__SoapCall('AuthenticateUser',array('parameters'=>$input));
My service method looks like this
[OperationContract]
AuthenticationData AuthenticateUser(AuthenticationData composite);
Using Fiddler is a good help when figuring out how to build your Soap stuff

Categories

Resources