Could someone here point me in the right direction about how I can override the serialization that occurs when my webservice is called?
Basically the end result I am aiming for is appending a TIMESTAMP to all objects returned from my webservice but only when the JavascriptSerializer is being used in my webservice as opposed to the XML serializer.
So for example below is a method that is contained in my webservice.
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=True)> _
Public Function GetSettingData(ByVal Username As String, ByVal Password As String) As SettingList
When the webservice is called (As a GET request) at some point the JavascriptSerializer is invoked and my objects parsed and outputted as JSON. I am assuming that somewhere during that invokation I can insert my own version of the JavascriptSerializer and do as required?
Anyone able to guide me here?
(PS: I am well aware that I can return strings from all my webservices and perform the serialization as required in the actual webmethod call but I am looking for a 'better' solution then that (besides that would mean I would need different methods if I wanted to return XML))
You can use Stream or Message classes as return types, then you can implement your custom serialization. See for example How to set Json.Net as the default serializer for WCF REST service as an example.
Related
I am using Web APi, as I am new to this, I dont know much about it.
I am trying to implement search, as of now I am starting with only text search, but later there may be huge search criteria. for one text that is easy, as web api works good with
primitive data types. Now I want to create a class of filter, say the pagenumber , the pagesize also all the search criteria, so I created a class. I have created a MVC application which is communicating with the web api, the web api returns Json data, then I de-serialize it to model. I am stuck with the complex object part, also as of now I am using a list to get the data, later that will be replaced by data base. Following is the code.
public IEnumerable<Document> Get(PaggingDetails request) //public async Task<IEnumerable<Note>> GetNotes() for Async (DB)
{
return _repository.GetAll(pagedetails.PageNumber, pagedetails.PageSize, pagedetails.PageFilter);
//return await db.Notes.ToListAsync<Note>(); for async
}
public string GetPage(int pagenumber,int pagesize,string pagefilter)
{
try
{
PaggingDetails PageDetails = new PaggingDetails();
PageDetails.PageFilter = pagefilter;
PageDetails.PageSize = pagesize;
PageDetails.PageNumber = pagenumber;
return new System.Net.WebClient().DownloadString
("http://.../api/Document/?pagedetails=" +
PageDetails);
//new HttpClient().GetStringAsync("http://localhost:18545/api/Emails"); for async
//also pass parameters
}
catch (Exception ex)
{
}
return "";
}
By deafult, you cannot use a class as the type of parameter of a GET Web API action. You need to use individual parameters of single types.
If you want to use a class as parameter nothing stops you to use a POST action, in which you can include the data without any problem.
However you can force a complex parameter of a GET action to be read from the URI by decorating the comples attribute with [FromUri].
You can read this document to better understand Web API parameter binding:
Parameter Binding in ASP.NET Web API
By default, Web API uses the following rules to bind parameters:
If the parameter is a “simple” type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)
For complex types, Web API tries to read the value from the message body, using a media-type formatter.
This is the standard way of working. If you use the [FromUri] attribute, the action selector won't be able to choose between different Get methods that receive different complex types. If you use a route with controller and action segments, you won't have that problem, becaus ethe actions selector will choose by action name, no matter what the aprameters are.
I don't like using the [FromUri] for this reason, and beacuse it's not the natural way to work with the GET action. But you can use it with the necessary precautions.
I'm trying to get a VB.NET ASMX web service to return raw JSON (without the .d). I've declared a plethora of attributes but still get XML back. The signature of my method is:
<WebInvoke(BodyStyle:=WebMessageBodyStyle.Bare, RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json, Method:="GET")>
<WebGet(BodyStyle:=WebMessageBodyStyle.Bare, ResponseFormat:=ResponseFormat.Json)>
<ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Json)>
<WebMethod()>
Public Function TryLogin(ByVal userName As String, ByVal passwordHash As String) As LoginResult
Am I missing a declaration?
EDIT: I've tried requesting via POST, but I still get XML.
I think your web method needs to return an object type.
Use attribute ScriptService on your web-service class.
Try putting <ScriptService> attribute on the class.
Add this line, on its own line, two spaces below your Imports statements:
<System.Web.Script.Services.ScriptService()> _
and immediately above the remaining code.
webservice.PService pService = new Project.webservice.PService();
var v3 = passportService.HelloWorld();
Response.Write(v3);
I debugged it and found that v3 was string. Why? Should not a webservcie always return xml?
The webservice was:
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
Edit:
What if I want an object or a list of objects to be returned by the webservcie?
I suggest you might want to start with Microsoft.
Then have a look at returning objects.
Whilst the webservice transport layer uses XML, there's an awful lot of stuff in there that your application code typically isn't going to care about, which is why the client proxies strip it all out for you, so that you're left with the the bits that you're interested in.
As long as the object you want to return from your WebMethod is serializable, you should be able to just define it as a return type and it'll get encoded for you. When you generate the client side proxy, a similar object will be created for the request to be deserialized into.
Returning collections of objects from your WebMethod is essentially the same, although it's worth noting that List<T> is converted to an Array, over the wire.
The web service takes an object, and serialises it to XML, and sends that XML back to the client. The client/proxy parses that XML, and deserialises it back to an object. The type returned is determined by your web method signature. If you wanted to see the original XML, you could do so by inspecting the HTTP messages, but the point of using the proxy is that it does the conversion for you.
I am using local resource strings in ASP. My strings are something like "This is a {0}"
I am using String.Format to replace the {0} value.
In anycase, rather the put this code in every page, I wanted to create a Static/Shared method that any page could call. I had thought that I could pass the page in and call the GetLocalResourceObject() method. GetLocalResourceObject() is protected so its not valid.
Is there a way to call this external to the code-behind?
Shared Function GetPatternedResourceString(Byval P as Page, ByVal key As String, ByVal replacement As String) As String
Return String.Format(p.GetLocalResourceObject(key), replacement)
End Function
I realize there are some other ways to get a local resource, I think there is one on HttpContext but you need to do some extra work and pass in url paths, etc.
This is actually the same problem listed here
VB.NET: Extension method for pages that uses GetLocalResourceObject
GetLocalResourceObject() - Gets a page-level resource object based on the specified VirtualPath and ResourceKey properties. For more clarification you should read this
I've created a web service , which can a method to set the user credential using Microsoft.Web.Services3.WebServicesClientProtocol. The sample code is :
<WebMethod()> _
Public Sub ClientCredential1(Of TSecurityToken As SecurityToken)_
(ByVal UserCred As Microsoft.Web.Services3.Security.Tokens.UsernameToken)
Dim cProxy As New Microsoft.Web.Services3.WebServicesClientProtocol()
cProxy.SetClientCredential(UserCred)
End Sub
When I run the web service it gives this error:
"Microsoft.Web.Services3.Security.Tokens.UsernameToken cannot be serialized because it does not have a parameterless constructor."
Does any one know where is the problem ?
The root of the problem here is that the class Microsoft.Web.Services3.Security.Tokens.UsernameToken doesn't have a parameter-less constructor. It's got 3 of them, but they all demand a parameter. UsernameToken constructors on MSDN.
UsernameToken (XmlElement)
UsernameToken (String, String)
UsernameToken (String, String, PasswordOption)
The problem is that during deserialization, XmlSerializer calls the parameterless constructor to create an instance of that class. It can't deserialize a type that doesn't have a parameterless constructor.
I get the sense there's not much you can do to work around this problem. I'd only suggest creating a partial class, and implementing that zero-param constructor yourself.
'ensure namespacing is correct.
Public Partial Class UsernameToken
Public Sub New()
End Sub
End Class
p. campbell is right, it's because the XmlSerializer requires a parameterless constructor.
I don't know WSE, but from looking at this post on Aleem's Weblog, I don't think the UsernameToken is supposed to be passed as a regular argument to a web method - it's supposed to be passed in the WS-Security SOAP headers. You get the proxy to pass it in the headers by calling SetClientCredential(). Here's the example from the above blog post:
Dim oService As New WSETestService.ServiceWse
Dim U As New UsernameToken(“<User_Name>”, “<Password>”, PasswordOption.SendHashed)
oService.SetClientCredential(U)
You can't use a parameter of the type Microsoft.Web.Services3.Security.Tokens.UsernameToken in a web service, as it's not possible to serialise (or more specifically not possible to deserialise).
Create a class that just contains the data that you need to create a UsernameToken and use as parameter type. The client side would not create a real UsernameToken object anyway, there is a proxy class created from the WSDL information.