JSON From ASMX Service - asp.net

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.

Related

MapHttpRoute vs MapRoute for basic POST WebAPI

Given the following simple Web API (not part of an MVC project, just an empty ASP.NET site) which I've taken from a tutorial:
Public Class AwesomeController
Inherits ApiController
Public Function [Get]() As String
Return "Hello. The time is " & DateTime.Now.ToString
End Function
Public Function Post(<FromBody> yourName As String) As String
Return String.Format("Hi {0}, you posted here at {1}", yourName, DateTime.Now.ToString)
End Function
End Class
I am creating the Route within global.asax like this:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
GlobalConfiguration.Configuration.Routes.Add("default", New HttpRoute("{controller}"))
End Sub
This works fine, but I've read that WebAPI Routing should preferably be created using MapHttpRoute so that the service can exist in isolation. Is this true?
If so, can anyone post the code to replace my global.asax version?
Update
I figured out the last bit, but would still appreciate knowing whether there is a 'correct' way?
RouteTable.Routes.MapHttpRoute("default", "{controller}")
The MapHttpRoute extension method is simply a convenient way to register HttpRoute instances in your routing table. It's perfectly okay to manually create and register an HttpRoute without making use of the shorthand method, though.
If you want to understand the inner workings of MapHttpRoute, take a look at the source code: HttpRouteCollectionExtensions.cs.

Why does AutoCompleteExtender WebService fail to be called when function is Shared?

I had a problem (which is now fixed) but I've no idea why...
I have an Ajax AutoCompleteExtender with a WebService method to populate like
<WebMethod()> _
Public Shared Function populateACE(prefixText As String) As List(Of String)
However this didn't work - I put a breakpoint in, and it didn't even get hit. However...
<WebMethod()> _
Public Function populateACE(prefixText As String) As List(Of String)
..does work (the only difference being not Shared).
Fair enough, but why? If you have an instance of a class then you can access Shared methods of it; if you don't have an instance of a class then you can access Shared methods of it. So what is going on behind the scenes?
If you're calling a page method then it must be Shared/static. But when calling methods attached to asmx services, accordining to John Saunders in this question,
Why are Static Methods not Usable as Web Service Operations in ASMX Web Services?, web methods can't be Shared/static by design.
I'd have to guess that both are design limitations in the pipelines that retrieve pages vs. web methods.
To quote the relevant part from John Saunders' answer..
The answer is: because you can't.
It's not designed that way. The design is that an instance of the web
service class will be created, and then an instance method will be
called.
..but still worth having a look at the full answer.

Is there a way to move a call to ASP GetLocalResourceObject to a external static/shared method?

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

web service error ' it does not have a parameterless constructor '

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.

ASP.Net Webservice Serialization

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.

Resources