Please look at the code below and help me to figure out what am I doing wrong in my web service code. I want to set up an asp.net web service that can be consumed using an JSONP. I am using Jquery at client side to access the site. Even after setting up proper attributes my web service still emits xml due to which the aynch call fails.
Web Service
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
public WebService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
[ScriptMethod(ResponseFormat= ResponseFormat.Json, XmlSerializeString=false, UseHttpGet=true)]
public string HelloWorld(int id, string __callback) {
return __callback + "({message: 'Hello World'})";
}
}
Web Service Response:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">test({message: 'Hello World'})</string>
Web.Config:
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="*" path="*_AppService.axd" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler,
System.Web.Extensions, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"
validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule"
type="System.Web.Handlers.ScriptModule, System.Web.Extensions,
Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
</httpModules>
Javascript
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "http://localhost:54404/jsonp/webservice.asmx/HelloWorld?id=2&__callback=?", //?jsonp=MatchSvcCallback
dataType: "jsonp",
data: {},
//jsonp : "MatchSvcCallback",
success: function(msg) {
alert("Inside success callback function"); // not being called
},
error: function(xhr, msg){
var response = JSON.parse(xhr.responseText);
}
});
The js code works with an handler, but fails for the webservice due to xml response.
I think the problem here is because jQuery doesn't set the Content-Type header in the HTTP request for HTTP GET's when using $.ajax(). It only gets sent if the request type is 'POST'. This seems to be the case for both dataType: "jsonp" and dataType: "json".
I tried your example and watched the request/response exchange in Fiddler and sure enough I don't see Content-Type: application/xml; charset=UTF-8 being sent in the headers for HTTP GET requests. The header does get sent if using HTTP POST. I'm guessing the presence of this header is a cue for the ASP.NET web service plumbing to decide whether to return either a JSON or XML formatted response.
It seems you're not the only one with this problem, see the following article on the on Elegant Code website:
Calling Remote ASP.NET Web Services from JQuery
The solution appears to be one of the following:
Use a HttpModule to inject the Content-Type: application/xml; charset=UTF-8 header into the request stream as described in the article above.
Use a HttpHandler for the endpoint as you explained you were doing prior to using an ASP.NET web service.
Try Rick Strahl's page based approach
in the following article (which
is in effect a HttpHandler anyway): JSONP for cross-site Callbacks.
Related
Update: Problem solved. Read on.
Any idea why it's apparently not possible anymore to add custom IHttpModules?
My question is related to: HttpModule.Init - safely add HttpApplication.BeginRequest handler in IIS7 integrated mode
However this question is rather old, unanswered and has no SharePoint context. I CAN add my HttpModule to any standard ASP.NET WebForms page.
SharePoint is being hosted in IIS 8. AppPool runs in Integrated Mode. Framework level is 4.0+.
namespace My.Namespace
{
using System;
using System.Web;
public class CustomHttpModule : IHttpModule
{
private static readonly object mutex = new object();
private static bool _isInitialized;
public void Init(HttpApplication context)
{
if (!_isInitialized)
{
lock (mutex)
{
if (_isInitialized) return;
context.BeginRequest += BeginRequest;
_isInitialized = true;
}
}
}
private void BeginRequest(object sender, EventArgs e)
{
}
public void Dispose()
{
}
}
}
Result:
[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.PipelineModuleStepContainer.GetEventCount(RequestNotification notification, Boolean isPostEvent) +30
System.Web.PipelineStepManager.ResumeSteps(Exception error) +1098
System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +135
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +604
The web.config looks as follows:
<system.webServer>
<!-- further elements omitted -->
<modules runAllManagedModulesForAllRequests="true">
<remove name="AnonymousIdentification" />
<remove name="FileAuthorization" />
<remove name="Profile" />
<remove name="WebDAVModule" />
<remove name="Session" />
<add name="SPNativeRequestModule" preCondition="integratedMode" />
<add name="SPRequestModule" preCondition="integratedMode" type="Microsoft.SharePoint.ApplicationRuntime.SPRequestModule, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="SharePoint14Module" preCondition="integratedMode" />
<add name="StateServiceModule" type="Microsoft.Office.Server.Administration.StateModule, Microsoft.Office.Server, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="PublishingHttpModule" type="Microsoft.SharePoint.Publishing.PublishingHttpModule, Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="DesignHttpModule" preCondition="integratedMode" type="Microsoft.SharePoint.Publishing.Design.DesignHttpModule, Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="FederatedAuthentication" type="Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule, Microsoft.SharePoint.IdentityModel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="SessionAuthentication" type="Microsoft.SharePoint.IdentityModel.SPSessionAuthenticationModule, Microsoft.SharePoint.IdentityModel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="SPWindowsClaimsAuthentication" type="Microsoft.SharePoint.IdentityModel.SPWindowsClaimsAuthenticationHttpModule, Microsoft.SharePoint.IdentityModel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="SPApplicationAuthentication" type="Microsoft.SharePoint.IdentityModel.SPApplicationAuthenticationModule, Microsoft.SharePoint.IdentityModel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="CustomModule" type="My.Namespace.CustomHttpModule, My.Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=066b2229567b6747" />
</modules>
<!-- further elements omitted -->
</system.webServer>
As soon as I don't attach to the BeginRequest event anymore the page works again. But obviously my http module is rendered useless.
Edit 2013.09.19: Init() is being called twice upon application start. If I attach my event only on the second call the application works but the event doesn't fire.
Edit 2013.09.20: Problem presumably solved. The fact that my Init() method is triggered twice (and no Dispose() is called in between) led me to the assumption there might actually be two co-existing instances of my IHttpModule. And while my previous observation showed that the second instance can have the event attached (not firing, but no negative impact on the application as well) - it apparently is not true vice versa (which is the case with my static _isInitialized "lock").
**So both instances of the IHttpModule need to have the same "configuration" (eventhandlers attached). It is totally normal to have more than one HttpApplication instance running. That's something ASP.NET (or IIS) does internally for optimization purposes. That's the key thing to remember :)
Problem solved. Edited question. See Edit 2013.09.20.
I have jquery call an asp.net webservice with an integer.
On our legaacy application which was ported to .net 4.0 I cannot get this call to work.
I can call a method which has no parameters but sending data to the web method returns the following error:
System.InvalidOperationException: Request format is invalid: application/json; charset=UTF-8.
at System.Web.Services.Protocols.HttpServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
I created exactly the same code in a blank project and it worked fine. I couldnt see anything in the web.config that the blank project added that would make a difference.
the Jquery Code
$.ajax({
type: "POST",
url: "/WebService1.asmx/Test",
data: JSON.stringify({"code": 1234}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert(msg);
}
});
My Web Service Code
<ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class WebService1
Inherits WebService
<WebMethod()>
Public Function Test(ByVal code As Integer) As String
Return "success"
End Function
<WebMethod()>
Public Function Hello() As String
Return "hello"
End Function
End Class
Web Config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
</appSettings>
<connectionStrings>
</connectionStrings>
<system.web>
<httpRuntime enableVersionHeader="false" />
<httpCookies httpOnlyCookies="true" requireSSL="false" lockItem="true" />
<trace enabled="false" pageOutput="true" requestLimit="40" localOnly="true"/>
<httpModules>
</httpModules>
<compilation debug="true" strict="true" explicit="true" targetFramework="4.0">
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
</pages>
<authentication mode="Forms">
<httpHandlers>
</httpHandlers>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
</modules>
<handlers>
</handlers>
<httpErrors errorMode="Custom" >
</httpErrors>
</system.webServer>
</configuration>
DOH, I was working in the wrong web.config.
Like a lot of questions on SO the solution was to add the following.
<system.webServer>
<handlers>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</handlers>
</system.webServer>
I had the same problem and ending up running this command...
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>aspnet_regiis.exe -i
Note that you will need your command prompt in Administrator mode for it to work.
I am trying to use jQuery to directly call ASP.NET AJAX page methods. I'm using encosia.com as a reference. My inline javascript is
<script type="text/javascript">
$(document).ready(function() {
// Add the page method call as an onclick handler for the div.
$("#Result").click(function() {
$.ajax({
type: "POST",
url: "Default.aspx/GetDate",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// Replace the div's content with the page method's return.
$("#Result").text(msg.d);
}
});
});
});
</script>
<div id="Result">Click here for the time.</div>
with my webmethod being
<WebMethod()> _
Public Shared Function GetDate() As String
Return DateTime.Now.ToString()
End Function
I would use FF and check POST sent, but since where I'm at currently only has IE 7 this is a little hard to do. Other relevent information, ASP.net 2.0. Does anyone know what I'm doing wrong?
Update
web.config - pre-existing still not working
<httpModules>
<remove name="FormsAuthentication" />
<remove name="PassportAuthentication" />
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</httpModules>
Since you're using ASP.NET 2.0, you'll need to install the ASP.NET AJAX Extensions, like Joe Enos mentioned. I have a bit more info on the necessary configuration work here: http://encosia.com/asmx-scriptservice-mistakes-installation-and-configuration/
Additionally, the .d wrapper around the response is an addition that didn't come until ASP.NET 3.5. So, even if you've got everything else working right, your msg.d will be undefined in ASP.NET 2.0. Omit the .d and just make that:
success: function(msg) {
// Replace the div's content with the page method's return.
$("#Result").text(msg);
}
In .NET 2.0, you need to make sure you install the ASP.NET AJAX extensions. In .NET 3.5 and 4.0, the encosia solution works without any modifications.
I don't remember exactly what you need to install, but it might be this.
Have you checked your web.config to allow page methods?
<system.web>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
</system.web>
There is a similar issue here at this post here
Since the installation of SP1 we are facing problems in calling asmx pages from JQuery client code.
IIS is pointing the JQuery post call to his default 404 page.
We did a roleback of our environment to assert this issue is caused by SP1 and tests confirm it.
Waiting for a fix #MS
Technologies used:
ASP.Net 4.0 -
JQuery -
IIS 7.5 -
Windows 2008 R2 SP1
--Bart
Code Sample calling (front-end):
// Code to load vars...
$.ajax({
type: "POST",
url: "/Handlers/ProductRating.asmx/RateProduct",
data: "{'uniqueId':'" + uniqueId + "','productId':'" + productId + "','points':" + points.toString() + ",'showOwnScore':" + showOwnScore.toString() + "}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(response) {
alert('success');
},
failure: function(msg) {
alert('something went wrong');
}
});
}
Code back-end:
[ScriptService]
public class ProductRating : System.Web.Services.WebService
{
[WebMethod(EnableSession=true)]
public RateProductResponse RateProduct(Guid uniqueId, Guid productId, int points, bool showOwnScore)
{
//Implementation
}
Snapshot1 : With SP1:
http://img812.imageshack.us/i/capture2r.png/
Snapshot2 : Without SP1:
http://img190.imageshack.us/i/capture1qx.png/
I was able to get this working with the following addition to my web.config
I saw another site that suggested clearing the handlers, but that made everything way worse. With this update, I was able to call my web services once again.
<system.webServer>
<handlers>
<add name="AsmxRoutingHandler" verb="*" path="*.asmx" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</handlers>
</system.webServer>
I had the same problem.
Create a Web.Config file containing the following lines:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.web>
<httpHandlers>
<clear />
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="True" />
</httpHandlers>
</system.web>
</location>
</configuration>
Copy this into the directory(s) where you serve out your affected scripts, and restart your web server.
These lines will override your preferred HttpHandlers and set it to use the default handlers instead.
Good luck!
Judging by your screenshots, that seems an awful lot like a URL rewriting issue. Does your site have any overly-greedy URL rewrite rules at the IIS level that could be 302 redirecting /Handlers/ProductRating.asmx/RateProduct?
If you do have rewrite rules, can you try disabling them temporarily to see if that fixes the ASMX issue?
I'm trying to call a ASP.NET web service from Javascript, and it won't recognize the Web Method, even when I fully qualify the name, I'm trying to figure out what is wrong.
Here is the part of my web.config file:
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
</httpHandlers>
Here is my web service declarations
[WebService(Namespace = "http://tempuri.org")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class SavingService : System.Web.Services.WebService
{
[WebMethod]
public static void SaveToDB(string runCode, string container,
string productType, string inspector, string[][] scoregrid, string notes)
and here is the javascript (QCApp4 is my project's namespace):
function PrepToSave()
{
....
QCApp4.SavingService.SaveToDB(codev, containerv, prodtype, inspector, scoregrid, notes);
}
scoregrid is declared on the js side as a jagged 2d array using the Array() command. That was the only worry I had with regard to the parameters of the web service.
And here is the service reference:
<asp:ScriptManager id="scriptmng" runat="server">
<Services>
<asp:ServiceReference Path="~/SavingService.asmx" />
</Services>
</asp:ScriptManager>
I get errors whether I call the web method directly, or call it like SavingService.SaveToDB, or with the full Qualifiers. The error I get says that SaveToDB is not defined. SavingService is not defined, QCApp4 is not defined, depending on what the first part of the qualified name is entered as.
Am I missing something? Is there something I've set incorrectly?
It turns out I had made my WebMethod static, of course now I'm getting an error in the error console of:
Error: [Exception... "'Sys.Net.WebServiceFailedException: Sys.Net.WebServiceFailedException: The server method 'SaveToDB' failed with the following error: System.NullReferenceException-- Object reference not set to an instance of an object.' when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x8057001c (NS_ERROR_XPC_JS_THREW_JS_OBJECT)" location: "" data: no]
If you set the InlineScript attribute on the ServiceReference element, it'll write out the JavaScript methods inline with the HTML so you can see exactly what you need to call or if you're calling the wrong thing:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/SavingService.asmx" InlineScript="true" />
</Services>
</asp:ScriptManager>
I screwed up two things with this. I went back and found the video I had previously watched on setting these web services up.
I realized, I had accidentally made the web method static, and also forgotten to add the callback method parameters. Once I added a on complete and an on error handler, it worked fine, no errors in the Error Console.