Custom SOAP response of ASMX service - asp.net

I'm trying to implement a custom SOAP response of the legacy web service.
At the moment it has the following format:
<ServiceResponse>
<ServiceResult>some return value</ServiceResult>
</ServiceResponse>
I need to add string value like this:
<ServiceResponse>NEW VALUE
<ServiceResult>some return value</ServiceResult>
</ServiceResponse>
I'm not sure if it is a good idea at all? Is this SOAP xml valid? If yes, how it can be accomplished?
Any suggestion or idea would be appreciated

That xml isn't valid, in a node you can't have both text and a child node like you have there.
If you're writing your webservice in .NET I would advise you construct a Serializable class that represents the data structure that you want to return, when you create your webservice it will automatically get converted into a valid soap data structure. You will also be able to see the definition of your response when you browse the WSDL at Service.asmx?wsdl.
If you'd like some more info on SOAP checkout the specification at w3.org
Edit: Removed false claim as pointed out by marc_s

Related

Can I configure asp.net so some responses are serialized as camelCase and some as PascalCase?

I have an API with two clients: OldClient and newClient. I currently have this in Startup.cs so my json responses are serialized as PascalCase, i.e. as per all my .net objects which have first letter capitalized.
services.AddControllers().AddJsonOptions(jsonOptions =>
{
// So json output is like 'SomeId' instead of 'someId':
jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null;
...
}
OldClient loves this format. However, newClient would really prefer camelCase.
Is there a way I can configure my app to respond with camelCase for newClient requests and PascalCase for OldClient requests? newClient can send a header to indicate that it wants camelCase.
You can check out this issue on aspnetcore's github page
The possibility of using specific JSON Serializer Options on a per-controller basis hasn't been implemented yet. It has been moved to ".NET 8 planning", which means it's still a ways-away.
Meanwhile, you could work around this issue by:
For data reception and model-binding, you could create a Custom ModelBinder by implementing IModelBinder interface in a ModelBinderAttribute in order to utilize your specific JSON Serialization options. Then, you could simply add the attribute to the endpoints where you need it.
For data responses, you could simply use:
return new JsonResult([object], [CustomJSONSerializationSettings]);
It's quite annoying to have to modify these per-endpoint, but it seems like it's the only way until the feature is added in .net 8 (if we're lucky).

Apigility InputFilter injection

Given I am posting to an endpoint as so:
POST http://foo.com/user/:user_id/articles
{
"content": "some text"
}
when I configure the Validator within the config I am struggling to find how to inject the :user_id from the route along with the "content" from the body. So my Validator is stuck trying to validate if "content" is ok without the :user_id.
What is the proper Apigility way to inject IDs (or even ideally objects) from route parameters into the Validator(s) along with the normal body $data payload?
Many thanks
As far as i know, apigility has no way to validate the route parameters.
Personally i validate them in de resource or the controller.
That way i can do some more complex validation, like does this id exist?
If you want an object as a route parameter, you van try serializing the object and putting that in your parameter.
But i would advice against this. Would you even trust an external party to provide you with whole objects?
If you need some user info you could look into JWT or similar techniques.
JWT is a authorisation token that also contains any data (it's json based).
Now, any body params can be validated.
In the apigility ui, you can go to fields, and add the fields you want to validate there (or it should be all of them for simplicity).
Then you can assign filters and validators here. Even custom ones you have configured in your zf2 application.

JSON + SOAP - Is DataContract necessary?

Here's my problem.
I'm using SOAP to retrieve information from a third-party web service.
Response time is too high, so I was planning on using JSON instead, at least in a couple of methods.
For this I'm using DataContractJsonSerializer, but I seem to be having some trouble.
For example, in SOAP there's a method called getAvailablePublic with returns an object of type getAvailablePublicResponse.
There's an equivalent for this method in JSON, which also returns a an object of type getAvailablePublicResponse.
In order to deserialize the information I needed to create a couple of data contracts, and here are my concerns:
Do I really need to create a DataContract? Why can't I use getAvailablePublicResponse object from asmx?
The problem is that if I create a DataContract, I need to use a different name other than getAvailablePublicResponse, as I would have two objects with the same name (the one created by me, and the one from SOAP), and this would require making several changes in my solution.
Hope this makes sense.
Thanks.
Can you post your client code that is making the call to the web service? I don't know what you are using now, but I'm a fan of RestSharp for making remote calls and serializing JSON to C# classes. Something like this:
RestClient client = new RestClient("http://some.domain.com/someservice?someparam=yes");
var results = client.Execute<MyGreatDTOClass>(new RestRequest(Method.GET));

Why have a separate call to get Json?

I need to get some Json to the client side from the server and it's somewhat troublesome as almost all tutorials assume an Ajax call to a separate action to get the Json.
This led me to think that there must be some reason why it is done this way. In Asp.Net MVC we can pass a Model along with the view to get the information but we can't seem to easily pass a Json object. Instead you are supposed to make a separate call to get this information.
What if the Json info is known when the page is generated, why not generate it at the same time?
I'm sorry if I wasn't clear enough. While it's nice to hear of ways to get Json to the client, the question is actually whether there is a specific reason the Ajax call method is much more popular, like security or anything like that.
Can you put something like this into your view? (rough pseudo code, assuming using a Razor view)
< script >
var myJSON = { Field: #model.Field, Field2: #model.Field2 };
< /script >
Because you do not need both at the same time... on the first call will be to get html (the view of the data - represented by a view model), and any ajax calls will be to get the possibly updated data (json serialized view model).
No reason why you can't. You could use the javacript serializer to create a JSON string that drop on the page. You could also create an action that return the json string that you called from a script tag.
What you want if you're using KnockOut, would be the Mapping plugin that turns an ordinary JS object, like that generated above, into an observable ready for KnockOut to use. See here from info. http://knockoutjs.com/documentation/plugins-mapping.html
You can use content-negotiation by setting accept header. This is considered a best practice (and according to some RESTful).
This needs to be supported and implemented at server as well. ASP NET MVC does not make it easy to support content-negotiation and you have to implement it yourself by if-else or using ActionFilter and implementing action selector.

i want to pass the array of request to web service at once...it it possible?

I am working with some web services and I want to pass the array of request to the web service at once and the output should be returned once for the whole array of request.
For example, let's say I am requesting the city details by city name. I want to build the array of city names and pass it to the web service and get all the details in one response.
I am using ASP.NET
<AirAvailability_6_2>
<AirAvailMods>
<GenAvail>
<NumSeats>1</NumSeats>
<Class><![CDATA[ ]]></Class>
<StartDt>20091214</StartDt>
<StartPt>LON</StartPt>
<EndPt>AAH</EndPt>
<StartTm>1200</StartTm>
<TmWndInd>D</TmWndInd>
<StartTmWnd>0800</StartTmWnd>
<EndTmWnd>1400</EndTmWnd>
<FltTypeInd></FltTypeInd>
<StartPtInd></StartPtInd>
<EndPtInd></EndPtInd>
<IgnoreTSPref></IgnoreTSPref>
</GenAvail>
</AirAvailMods></AirAvailability_6_2>
<AirAvailability_6_2>
<AirAvailMods>
<GenAvail>
<NumSeats>1</NumSeats>
<Class><![CDATA[ ]]></Class>
<StartDt>20091214</StartDt>
<StartPt>LON</StartPt>
<EndPt>AAH</EndPt>
<StartTm>1200</StartTm>
<TmWndInd>D</TmWndInd>
<StartTmWnd>0800</StartTmWnd>
<EndTmWnd>1400</EndTmWnd>
<FltTypeInd></FltTypeInd>
<StartPtInd></StartPtInd>
<EndPtInd></EndPtInd>
<IgnoreTSPref></IgnoreTSPref>
</GenAvail>
</AirAvailMods></AirAvailability_6_2>
declare the web method to accept an array. Declare the web method to return an array.
[WebMethod]
public CityDetails[] GetCityDetails(string[] names)
{
/// blah blah
}
If you are talking about an existing web service with an API you have no control over - you will have to stick with what this service offers. In other words if the existing API does not provide for batching requests you will have to feed the service one request at a time.
If, on the other hand, you are building the service yourself - noting prevents you from spelling out the API so that it can take an array of requests.
If you have control over both sides of the connection and they're both managed code, then you could create the custom object (serializable) and setup the web method to take in that object as its parameter.
I did this recently using JSON (giving me access from the client side of a web page). You set up the web service to accept a string parameter, and use a JSON Deserializer (DataContractJsonSerializer is one choice) to convert the request to your custom object.
This gives you the ability to pass in the specifics on multiple requests, and pass the results back out the same way (a custom collection object).
Let me know how this works out for you.'
Gabriel

Resources