Consume WCF service from JQuery - asp.net

I am trying to add a WCF service to my web control class project and allow my jquery client to consume the service. Ideally, I want to host the WCF service in the same project and allow a custom web control's (inside the same project) jQuery method consume the service. I'm not sure what I am doing wrong, but I am unable to make a connection between the jquery call and the service. Although there is no error, the break point on my service is never reached. Here is what I did:
Right Click on project and select Add
Select Web Service
This creates three files: Service1.vb, app.config, and IService1.vb
I edited the files to look like this:
Service1
Public Class Service1
Implements IService1
Public Function getUsers(ByVal prefixText As String) As List(Of String) Implements IService1.getUsers
Dim myList As New List(Of String)
With myList
.Add("Some String")
.Add("Another String")
End With
Return myList
End Function
End Class
IService1
Imports System.ServiceModel
<ServiceContract()>
Public Interface IService1
<OperationContract()> _
Function getUsers(ByVal prefixText As String) As List(Of String)
End Interface
And then I try to call it with the following jQuery:
$.ajax({
type: "POST",
url: 'Service1.vb/getUsers',
data: '{"prefixText":"' + getText + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert("success")
},
error: function (e) {
alert("Failed")
}
});
As I said, the break point on my getUsers function is never reached and the jquery success/failure alerts are never raised either. If someone can tell me how to reach the service and/or how to alert the error in my jQuery, I'd appreciate it. I left out the app.config stuff but can add it if it would be helpful.
thanks

This is a terrible misunderstanding in your code. By default, WCF uses Soap and Javascript/Jquery does not provide an easy way to invoke a SOAP Service.
You should use WCF Web HTTP Programming Model to expose WCF service operations to non-SOAP endpoints, like a REST-like service (can be called from JS)
Iy your are using WCF 4, this is quite easy.
Service Contract
<ServiceContract()>
Public Interface IService1
<OperationContract()>
<WebInvoke(BodyStyle:=WebMessageBodyStyle.Bare, RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json)>
Function getUsers() As List(Of String)
End Interface
Service Implementation
Public Class Service1
Implements IService1
Public Function getUsers(ByVal prefixText As String) As List(Of String) Implements IService1.getUsers
Dim myList As New List(Of String)
With myList
.Add("Some String")
.Add("Another String")
End With
Return myList
End Function
End Class
Service1.svc
<%# ServiceHost Language="VB"
Service="MvcApplication2.Service1"
CodeBehind="Service1.svc.vb"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
I won't explain you everything here, and continue reading here or with this example
Also note that WCF REST is less popular today since because of ASP.NET Web Api. I don't believe that WCF REST is deprecated, but to expose something on the Web, Web Api sounds like a better solution.

Related

Create a dataContract in separe file problem

Hi I need to create a class for return the data in WCF service. I followed the web at 5 simple steps to create your first RESTful service. However I get the error for . I searched the web and add the System.Runtime.Serialization.DataContractSerializer, Would someone tell me what should do. I am using VS2015 as the tool to build it. Thanks.
Imports System.Runtime.Serialization
Imports System.Collections.Generic
Imports System.Runtime.Serialization.DataContractSerializer
<DataContract>
Public Class Locations
<DataMember>
Public Property LocationName As String
<DataMember>
Public Property LocationID As Integer
End Class
Could you please share the error details with me?
As you know, we usually use the datacontract to transmit the complex data type which could be recognized by the client-side and server-side. so that the data could be serialized and transmitted normally between different platforms.
For the restful web service in WCF, we need to use the Webhttpbinding build the data channel and add the Webhttpbehavior to the service endpoint.
I have made a demo, wish it is useful to you.
Server-side.
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Web
Module Module1
Sub Main()
Dim uri As New Uri("http://localhost:900")
Dim binding As New WebHttpBinding()
binding.CrossDomainScriptAccessEnabled = True
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
Using sh As New ServiceHost(GetType(MyService), uri)
Dim se As ServiceEndpoint = sh.AddServiceEndpoint(GetType(IService), binding, uri)
se.EndpointBehaviors.Add(New WebHttpBehavior())
sh.Open()
Console.WriteLine("Service is ready")
Console.ReadLine()
sh.Close()
End Using
End Sub
<ServiceContract([Namespace]:="mydomain")>
Public Interface IService
<OperationContract>
<WebGet(ResponseFormat:=WebMessageFormat.Json)>
Function SayHello() As List(Of Product)
End Interface
Public Class MyService
Implements IService
Public Function SayHello() As List(Of Product) Implements IService.SayHello
Dim result = New List(Of Product)() From {
New Product With {
.Id = 1,
.Name = "Apple"
},
New Product With {
.Id = 2,
.Name = "Pear"
}
}
Return result
End Function
End Class
<DataContract([Namespace]:="mydomain")>
Public Class Product
<DataMember>
Public Property Id() As Integer
<DataMember>
Public Property Name() As String
End Class
End Module
Client.
$(function(){
$.ajax({
type:"GET",
url:"http://10.157.18.188:900/sayhello",
dataType:"jsonp",
success:function(d){
$.each(d,function(i,o){
console.log(o.Id);
console.log(o.Name);
})
}
})
})
Result.
Here is an official sample
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service

VB.Net Web Api Action not invoked

I have vb.net web api controller that I am trying to invoke but I'm getting back the following:
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:26944/api/employee/GetPerson/'.","MessageDetail":"No action was found on the controller 'Employee' that matches the request."}
This is the web controller:
Public Class EmployeeController
Inherits ApiController
Private ReadOnly dbContext As MyEntities
Sub New()
Me.dbContext = New MyEntities
End Sub
<HttpGet>
<ActionName("GetPerson")>
Function Person(ByVal missionaryId As Integer) As IPRS_Data.getPersInfoDetail_Result
Return Me.dbContext.getPersInfoDetail(missionaryId).First
End Function
End Class
WebApiConfig:
Public Shared Sub Register(ByVal config As HttpConfiguration)
' Web API configuration and services
' Web API routes
config.MapHttpAttributeRoutes()
config.Routes.MapHttpRoute(
name:="DefaultApi",
routeTemplate:="api/{controller}/{id}",
defaults:=New With {.id = RouteParameter.Optional}
)
Dim xmlFormat = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(Function(t) t.MediaType = "application/xml")
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(xmlFormat)
End Sub
I'm invoking the service using: appbase/api/employee/GetPerson/
Your method is decorated with HTTPGET and Actionname attribute. You don't need that if you have your method name starting with "Get" (like GetPerson). However, the Actionname is obsolete as it is not considered in your actual routing. Your routing is "api/{controller}/{id}". If you want your action name being considered you need to modify your routing to "api/{controller}/{action}/{id}". And if you want to have your id-param being considered per default routing you should rename the param in your method from missionaryId to just id.
Function Person(ByVal id As Integer) As IPRS_Data.getPersInfoDetail_Result
Return Me.dbContext.getPersInfoDetail(id).First
End Function
And that's the way how to invoke it (don't forget to pass an Id because there is no other "GET" method in your controller which works paramless.
appbase/api/employee/15
or
appbase/api/employee?id=15
and if you insist on missionaryId
appbase/api/employee?missionaryId=15

Return type XmlDocument of an Asp.Net webservice changes to XmlNode when accessing the webmethod

I have a Web Method in Web service which is returning an XmlDocument. The Web service works fine when i am executing it and providing the necessary parameters.
I have created a proxy to this service in another application.proxy is created well and good.
Now the problem is,when i try to access the methods from that service its getting all the methods from the service but the return type of the method is showing as XmlNode instead of XmlDocument.
Let us say for example:
Service.asmx
public class DataService : System.Web.Services.WebService
{
[WebMethod]
public XmlDocument GetData(int ID)
{
//Code Here
}
}
Now i have one windows application which is using this service.
Created an object to the service through proxy.
DRService.DataService drService = new DRService.DataService();
Now i am trying to access the service methods.
drService.GetData(1)
The return type of the above method call should be XmlDocument but it is returning XmlNode as return type.
Any idea why the retun type is XmlNode?
This is the expected behavior.

ASP.NET Web Service + Module + Public variable = thread safe?

In my ASP.NET Web Service I've included a module in which their are Public declared variables. Will they be thread-safe? Will they get mixed up upon simultaneous calls?
Those variables are mostly DatsSet, DataTable and SQLDataAdapter..
Partial code of the module:
Imports System.Data.OleDb
Imports System.Diagnostics
Module modCommon
Public bDoLog As Boolean
Public sCurrentODBC As String
Public cn As SqlConnection
Public Query1ds As DataSet
Public Query1 As DataTable
Public Query1adapter As SqlDataAdapter
#scripni
Thanks, as I'm not familiary with your suggestions, I will move everything locally.
Additionally, will the following variables be thread-safe?:
[ToolboxItem(False)]_
Public Class Service1
Inherits System.Web.Services.WebService
Dim sName As String
Dim sCurrentPath As String
[WebMethod()]_
Public Function Capture(ByVal sPath As String) As String
sName = "Joe"
End Function
End Class
If you're using web services than yes, you will have concurency problems when multiple services will try to access the same resource, and SqlConnection is definetly a resource you don't want shared.
You should make sure that you don't have simultaneous calls to the properties (for ex. by wrapping the fields with getters / setters and implementing locks in those methods) or by moving the code to a class and instantiating that class whenever you need it.

How to force ASMX web service to send JSON data to client on HTTP GET request?

I'm trying to use the official jQuery autocomplete plugin with an ASMX web service in an ASP.NET 3.5 Web Forms application. If I understand it correctly, the autocomplete plugin can only use HTTP GET to call a service (with two query string parameters: q and limit). I figured out how to make the web service respond to the HTTP GET calls, but I cannot figure out how to make it return JSON data (even though the service returns JSON data when I call it using jQuery $.ajax with type='POST', when called from the autocomplete plugin it always returns XML). Here are some code snippets:
Web service:
[ScriptService]
[WebService(Namespace = "http://tempuri.org/")]
public class UserWS: WebService
{
[WebMethod]
[ScriptMethod(UseHttpGet=true, ResponseFormat=ResponseFormat.Json)]
public List<UserDisplayInfo> GetUsers
(
string q,
int limit
)
{
List<UserDisplayInfo>users = GetUsers(q, limit);
return users.ToList();
}
}
Web page:
$("#test").autocomplete(
"./Services/UserWS.asmx/GetUsers",
{
dataType: 'json',
type: 'POST', // this setting is ignored
contentType: 'application/json;charset=utf-8',
parse: function(data)
{
//...
}
});
If this is not possible I wonder what would be a better alternative:
fixing autocomplete plugin to use HTTP POST and JSON data instead of GET and query string parameters;
using a different autocomplete plugin (I looked at a few, but at this point the official plugin has most recommendations, and I'm not sure if other plugins support HTTP POST);
an alternative to ASMX web service, such as WCF web service (I would not want to use WCF because ASMX web service is simpler to implement -- no web.config changes, no contracts, no interfaces -- and it gives me everything I need);
something else.
I found several similar questions at StackOverflow, but I did not find the answer that would work for me. Any (good) ideas?
Autocomplete plugin wants results in plain text format, not JSON. Each item should be on a separate line:
foo\n
bar\n
baz\n
Try replacing web service with generic handler (.ashx):
public class MyHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("foo\nbar\nbaz");
}
public bool IsReusable
{
get { return false; }
}
}
On the side note you can't use GET if you want ASMX web service to return JSON. See How to let an ASMX file output JSON.

Resources