I am learning how to connect an Android app to ASP.NET web service from an online tutorial. When learning, I replaced their web service with one I had written on my own and ran it on a PC from Visual Studio. Then, I called the method 'Add' in the web service from the Android app but I am getting this error:
java.net.MalformedURLException: Protocol not found
I believe there is something wrong with the SOAP_ADDRESS field below.
public final String SOAP_ACTION = "http://tempuri.org/Add";
public final String OPERATION_NAME = "Add";
public final String WSDL_TARGET_NAMESPACE = "http://tempuri.org/";
public final String SOAP_ADDRESS = "12.145.142.45:50428/WebService.asmx";
This is the code of my web service.
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
public WebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public int Add(int a, int b)
{
return a+b;
}
}
I think the error is showing up because I cannot specify IP addresses like that directly in Java code. So, my question is what is the correct SOAP_ADDRESS value for connecting the Android app to my ASP.NET web service?
I made a c# web service (new website > asp.net web service) with 1 function that was auto generated :
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public string Hello()
{
return "Hello User";
}
}
I also made a winform app and added a reference to that service and tried to call HelloWorldAsynch but all I had was HelloWorld
new ServiceReference1.Service1SoapClient().HelloWorldAsynch?
Does anyone know why is this happening?
It seems the problem is that I added the web service as a service reference and not as a web reference
Fix : http://msdn.microsoft.com/en-us/library/bb628649.aspx
I have a WCF REST service consumed in an ASP.Net site, from a page, using AJAX.
I want to be able to call methods from my service async, which means I will have callback handlers in my javascript code and when the methods finish, the output will be updated. The methods should run in different threads, because each method will take different time to complete their task
I have the code semi-working, but something strange is happening because the first time I execute the code after compiling, it works, running each call in a different threads but subsequent calls blocs the service, in such a way that each method call has to wait until the last call ends in order to execute the next one. And they are running on the same thread. I have had the same problem before when I was using Page Methods, and I solved it by disabling the session in the page but I have not figured it out how to do the same when consuming WCF REST services
Note: Methods complete time (running them async should take only 7 sec and the result should be: Execute1 - Execute3 - Execute2)
Execute1 --> 2 sec
Execute2 --> 7 sec
Execute3 --> 4 sec
Output After compiling
Output subsequent calls (this is the problem)
I will post the code...I'll try to simplify it as much as I can
Service Contract
[ServiceContract(
SessionMode = SessionMode.NotAllowed
)]
public interface IMyService
{
// I have other 3 methods like these: Execute2 and Execute3
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/Execute1",
Method = "POST")]
string Execute1(string param);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall
)]
public class MyService : IMyService
{
// I have other 3 methods like these: Execute2 (7 sec) and Execute3(4 sec)
public string Execute1(string param)
{
var t = Observable.Start(() => Thread.Sleep(2000), Scheduler.NewThread);
t.First();
return string.Format("Execute1 on: {0} count: {1} at: {2} thread: {3}", param, "0", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId.ToString());
}
}
ASPX page
<%# Page EnableSessionState="False" Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="RestService._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script type="text/javascript">
function callMethodAsync(url, data) {
$("#message").append("<br/>" + new Date());
$.ajax({
cache: false,
type: "POST",
async: true,
url: url,
data: '"de"',
contentType: "application/json",
dataType: "json",
success: function (msg) {
$("#message").append("<br/> " + msg);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
$(function () {
$("#callMany").click(function () {
$("#message").html("");
callMethodAsync("/Execute1", "hello");
callMethodAsync("/Execute2", "crazy");
callMethodAsync("/Execute3", "world");
});
});
</script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<input type="button" id="callMany" value="Post Many" />
<div id="message">
</div>
</asp:Content>
Web.config (relevant)
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
Global.asax
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
RouteTable.Routes.Add(new ServiceRoute("",
new WebServiceHostFactory(),
typeof(MyService)));
}
Edit 1
I have tried several combinations but the result is the same, I was testing using Visual Studio but now I am testing on IIS 7, and it's the same result
I have tried combinations of the following properties:
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple
)]
Also I removed the use of Rx, now I am just simulating long-process operations like this:
Thread.Sleep(2000);
But the result is the same.... After compiling, and deploying, (the first call) the service works correctly, it is executed on different threads giving the desired result, but subsequent calls run on the same thread.... I do not get it
I just noticed something, the first time after compiling works, and the last thread used is always the thread used on subsequent calls, and this thread is blocked, it's like if the other threads weren't disposed or something or if the last thread were blocked for some reason
Edit 2
This is the full code of this project (RestWCF.zip)
http://sdrv.ms/P9wW6D
I downloaded your source code to do some testing on my own. I managed to get it to work by adding this to the web.config:
<sessionState mode="Off"></sessionState>
The problem seem to be related to the Asp.Net session handling (seems to be different from WCF session).
Without this, Fiddler shows that the WCF service response is sending an ASP.NET_SessionId cookie. You Page level EnableSessionState="False" does not affect the service.
EDIT: I did some more testing to see if I could get it to work without having to turn off session state for the whole application. I got it working now. What I did was:
Create a new folder "ServiceFolder" under the root of the application
Moved the service interface and implementation to that folder
Then in Global.asax I changed the ServiceRoute registration:
RouteTable.Routes.Add(new ServiceRoute("ServiceFolder/",
new WebServiceHostFactory(),
typeof(MyService)));
In Default.aspx I changed:
$(function () {
$("#callMany").click(function () {
$("#message").html("");
callMethodAsync('<%=this.ResolveUrl("~/ServiceFolder/Execute1") %>', "hello");
callMethodAsync('<%=this.ResolveUrl("~/ServiceFolder/Execute2") %>', "crazy");
callMethodAsync('<%=this.ResolveUrl("~/ServiceFolder/Execute3") %>', "world");
});
});
Then, in order to control the cookie handling, I created an HttpModule:
using System;
using System.Web;
namespace RestService
{
public class TestPreventCookie : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.PostAcquireRequestState +=
(new EventHandler(this.Application_PostAcquireRequestState));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
//prevent session cookie from reaching the service
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if (context.Request.Path.StartsWith("/ServiceFolder"))
{
context.Request.Cookies.Remove("ASP.NET_SessionId");
}
}
private void Application_PostAcquireRequestState(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if (context.Request.Path.StartsWith("/ServiceFolder"))
{
var s = context.Session;
if (s != null)
s.Abandon();
}
}
}
}
And then I registered the module in web.config:
<httpModules>
<add name="TestPreventCookie" type="RestService.TestPreventCookie" />
</httpModules>
Finally, I change Default.aspx to allow session:
EnableSessionState="True"
After these changes, the parallell execution of the service call works. Obligatory disclaimer:
It works on my machine
The idea is that when the calls to the service are coming in, the HttpModule inspects the URL and, when necessary, removes the ASP.NET_SessionId cookie so it doesn't reach the service. And then in the Application_PostAcquireRequestState we immediately abandon the created session so we don't unnecessarily consume server memory for a lot of empty sessions.
With this solution, you get:
Parallell execution of service calls
You can still use Session in other parts of your application
At the cost of:
But you service must be called on a recognizable URL where session cookies are not needed
The server will create and abandon a lot of sessions
If you do not need Session or need it ReadOnly, you can change SessionStateBehavior for specific svc in Global.asax.cs. The sequential blocking will stop.
protected void Application_BeginRequest(object sender, EventArgs e) {
if (Request.Path.Contains("AjaxTestWCFService.svc")) {
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
}
}
Be warned however that SessionStateBehavior.ReadOnly will prevent writing to sessions without throwing exception. Written values will be returned as null.
I think changing your ConcurrencyMode to Multiple like below would fix your thread blocking issue:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple
)]
public class MyService : IMyService
{
}
I am only passingly familiar with Reactive, but something stood out that didn't look right.
public string Execute1(string param)
{
var t = Observable.Start(() => Thread.Sleep(2000), Scheduler.NewThread);
t.First();
return string.Format("Execute1 on: {0} count: {1} at: {2} thread: {3}", param, "0", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId.ToString());
}
In this code you are doing a Thread.Sleep in a new thread, followed by First(). The First() method blocks the current thread, so these two lines are no different to Thread.Sleep(2000). That gets Reactive out of the way. If you run with this code you get the same result, indicating that you are not getting multithreading.
The first logical cause of this is missing ConcurrencyMode=ConcurrencyMode.Multiple, which I understand you have tried. The next possibility is that you are running it on the built-in ASP.Net Development Server which, unless I am mistaken, does not support multithreading. Are you running it on an IIS instance?
I am not sure what you are trying to achieve, but t.Take(1) is non-blocking.
Update The culprit is aspNetCompatibilityEnabled="true" in web.config. If it is included you get the behavior mentioned. If it is not included (default=false), you get multi-threading. I don't yet know the logic behind this. With it set to false you lose some features as described here, including HttpContext and ASP.NET Sessions.
** Further update ** If you turn off aspNetCompatibilityEnabled, you can't using routing. I have tried a number of combinations including different bindings and transferMode settings, and they fool you by seeming to work for a while, and then going back to using the same thread. I also checked worker threads and am running out of ideas.
I have a WCF service in folder "Services":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web.Services;
using System.ServiceModel.Activation;
using System.Web.Script.Services;
namespace Application.Services
{
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ScriptService]
public class ProductTypeService
{
[OperationContract]
[WebMethod]
public string LoadMainGridProductType(string test)
{
return "Success";
}
}
}
and on page I try to call this service method from javascript:
$(document).ready(function () {
var counter = "test";
Application.Services.ProductTypeService.LoadMainGridProductType(counter, ResultLoadMainGridProductType, ErrorLoadMainGridProductType);
});
on page I also make conect to this service and javascript files:
<asp:ScriptManager ID="ScriptManager" runat="server">
<Scripts>
<asp:ScriptReference Path="~/Scripts/ProductType.js" />
</Scripts>
<Services>
<asp:ServiceReference Path="~/Services/ProductTypeService.svc" />
</Services>
</asp:ScriptManager>
but code fails on
Application.Services.ProductTypeService.LoadMainGridProductType(counter, ResultLoadMainGridProductType, ErrorLoadMainGridProductType);
Error : Error of implementation of Microsoft Jscript: "Application" is not certain.
How fix this???
Firstly, check to see if the WCF service is working correctly by navigating directly to it, e.g. http://localhost:(port-number)/Services/ProductTypeService.svc
I suspect that this wont work and give you some errors.
Secondly, check to make sure that the jsdebug javascript file has been generated and is included in the scripts loaded with the application.
Another person asked a similar question earlier.
How get namespace on javascript in asp.net web?
Greetings!
I'm new to WCF and I thought it would be similar to ASP.NET web services, but I'm unable to call a method from client-side JavaScript. My web form looks like this:
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="~/test.js" />
</Scripts>
<Services>
<asp:ServiceReference Path="~/MyService.svc" />
</Services>
</asp:ScriptManager>
</div>
<button onclick="test()">Click Me</button>
</form>
My service's interface looks like this:
namespace Test
{
[ServiceContract(Namespace = "Test")]
public interface IMyService
{
[OperationContract]
void DoWork();
[OperationContract]
string SayHi();
}
}
And here's its implementation:
namespace Test
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyService : IMyService
{
public void DoWork()
{
}
public string SayHi()
{
return "Hello, World!";
}
}
}
And finally the JavaScript:
function test() {
Test.MyService.SayHi(SayHiSuccess, SayHiError);
}
function SayHiSuccess(result) {
alert(result[0]);
}
function SayHiError(error) {
alert(error.toString());
}
It appears that the service's SayHi() method never executes, although I'm not sure why or how to being troubleshooting. Any suggestions?
You didn't post your web.config contents. What binding are you using? You should probably be using webHttpBinding.
Also, it may help to know your .svc file contents. Although I've never tried it, I understand that you don't have to modify web.config at all if you use WebScriptServiceHostFactory as your service host factory. That's as simple as modifying your .svc file as follows:
<%# ServiceHost Service="MyService"
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
%>
If all else fails, here are some resources for you:
Calling WCF Service from Javascript
Create a Simple WCF Web...
Your code looks OK. Should be working by right. You could try adding the WebService and the WebMethod attributes as well.
For debugging a WCF web service I normally use Fiddler to track HTTP calls while running the WCF code with a debugger attached (run in Visual Studio in most cases).