i have made webservice, and i am trying to consume it using javascript, but when i call the webservice method it gives the error Webservice not defined. I have given reference of it .
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="../WebService.asmx" />
</Services>
</asp:ScriptManager>
my method
[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
{
CultureInfo cul = new CultureInfo("gu-IN", true);
protected sdData s = new sdData();
protected component comp = new component();
public ClsVB objvb = new ClsVB();
DBAccess dbAccess = new DBAccess();
public WebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string SubmitDDIPo(string txtCaseNoDDIPO, int txtDDIPO, int txtAmount, string txtDDDate, string txtBank, string District_Code )
{
javascript method calling
<script type="text/javascript">
function addDDIPO() {
"DDIPOdiv".Obctrl().style.display = "block";
"fadeDiv".Obctrl().style.display = "block";
}
function submitDDIPO()
{
WebService.SubmitDDIPo("txtCaseNoDDIPO".Obctrl().value, "txtDDIPO".Obctrl().value, "txtAmount".Obctrl().value, "txtDDDate".Obctrl().value, "txtBank".Obctrl().value, Session["District_Code"].ToString(), ResultSubmitSucess, ResultFailure);
}
</script>
Is that something i am missing?
please help
Try to uncomment [System.Web.Script.Services.ScriptService].
If the uncommneted attribute doesn't work check the namespaces. ScriptManager create the javascript client proxy whith full path. Ej: namespace1.namespace2.WSClassName.Method(). You can also try to put the client proxy inline to see the js source to easyly find it with ServiceReference.InlineScript property.
Related
I seem to be stuck at developing a custom Key/Value pair provider for Amazon's System Manager Parameter Store (SSM) using NETFramework 4.7.1 that utilizes Microsoft.Configuration.ConfigurationBuilders.
The implementation:
using System;
using System.Collections.Generic;
using Amazon.SimpleSystemsManagement;
using Amazon.SimpleSystemsManagement.Model;
using Microsoft.Configuration.ConfigurationBuilders;
using System.Linq;
using System.Diagnostics;
using System.Collections.Specialized;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using System.Configuration;
using System.Threading.Tasks;
namespace AXS.Configurations
{
public class ParameterStoreConfigBuilder : KeyValueConfigBuilder
{
public const string envTag = "Environment";
public const string appNameTag = "AppName";
private IAmazonSimpleSystemsManagement client;
/// <summary>
/// Gets or sets an environment (dev|qa|staging|production)
/// </summary>
public string Environment { get; set; }
/// <summary>
/// Gets or sets a AppName
/// </summary>
public string AppName { get; set; }
public ParameterStoreConfigBuilder(IAmazonSimpleSystemsManagement client,
string appName,
string environment)
{
this.client = client;
Environment = environment.ToLower();
AppName = appName;
}
public ParameterStoreConfigBuilder()
{
client = new AmazonSimpleSystemsManagementClient();
}
public override string Description => "Parameter Store";
public override string Name => "SSM";
protected override void LazyInitialize(string name, NameValueCollection config)
{
Optional = false;
base.LazyInitialize(name, config);
string env = UpdateConfigSettingWithAppSettings(envTag);
if (string.IsNullOrWhiteSpace(env))
throw new ArgumentException($"environment must be specified with the '{envTag}' attribute.");
Environment = env;
string appName = UpdateConfigSettingWithAppSettings(appNameTag);
if (string.IsNullOrWhiteSpace(appName))
throw new ArgumentException($"appName must be specified with the '{appNameTag}' attribute.");
AppName = appName;
client = new AmazonSimpleSystemsManagementClient("","", Amazon.RegionEndpoint.USWest2);
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
Trace.TraceInformation($"return values prefix {prefix}");
if (client == null)
return null;
var parameters = new List<Parameter>();
string nextToken = null;
do
{
var response = client.GetParametersByPath(new GetParametersByPathRequest { Path = prefix, Recursive = true, WithDecryption = true, NextToken = nextToken });
nextToken = response.NextToken;
parameters.AddRange(response.Parameters);
} while (!string.IsNullOrEmpty(nextToken));
return parameters.Select(p => new
{
Key = p.Name,
p.Value
}).ToDictionary(parameter => parameter.Key, parameter => parameter.Value, StringComparer.OrdinalIgnoreCase);
}
public override string GetValue(string key)
{
return Task.Run(async () => { return await GetValueAsync(key); }).Result;
}
private async Task<string> GetValueAsync(string key)
{
var name = $"/{Environment}/{AppName}/{key.Replace(':', '/')}";
Trace.WriteLine($"get value async:{name}");
if (client == null)
return null;
try
{
Trace.TraceInformation($"fetch key {name}");
var request = new GetParameterRequest
{
Name = name,
WithDecryption = true
};
var response = await client.GetParameterAsync(request);
var parameter = response.Parameter;
var value = parameter.Type == ParameterType.SecureString ? "*****" : parameter.Value;
Trace.TraceInformation($"fetched name={name} value={value}");
return value;
}
catch (Exception e) when (Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException))) { }
return null;
}
}
}
The problem seems to be that AWS SSM client never gets created.
If I change the code and try to instantiate in the constructor I get a stack overflow exception due to recursion.
Any ideas on how to force to get AmazonSimpleSystemsManagementClient created?
The code uses guidance from https://github.com/aspnet/MicrosoftConfigurationBuilders
The App.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false"
requirePermission="true" />
</configSections>
<configBuilders>
<builders>
<add name="ParameterStore" Environment="development" AppName="myAppNameforParmStore" type="AXS.Configurations.ParameterStoreConfigBuilder, AXS.Configurations" />
<add name="Env" prefix="appsettings_" stripPrefix="true" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment, Version=2.0.0.0, Culture=neutral" />
</builders>
</configBuilders>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<appSettings configBuilders="Env,ParameterStore">
<add key="Url" value="URL Value for from paramter Store" />
<add key="Secret" value="Some Secret value decrypted" />
</appSettings>
</configuration>
Thanks
UPDATE
I posted an updated version of the AwsSsmConfigurationBuilder, and a sample ASP.NET Web Forms project that uses it, on my GitHub:
https://github.com/Kirkaiya/AwsSsmConfigBuilderPoC/
Disclaimer: This is a proof-of-concept (POC) for a custom ConfigurationBuilder for ASP.NET 4.7.1 or higher (running on .NET Framework obviously). It's a POC, so it doesn't do anything besides allow you store Configuration AppSettings in AWS Parameter Store (a feature of Simple Systems Manager). So, clearly, don't use this in production without productizing and testing it!
Prerequisites:
Your project must target .NET Framework 4.7.1 or higher
Include NuGet package Microsoft.Configuration.ConfigurationBuilders.Base
Have parameters in AWS SSM Parameter Store that have the same name (not counting the prefix) as parameters in your web.config file, and vice-versa.
Notes
In order to avoid recursively calling a concrete constructor or Initialize, I used a static constructor to instantiate the AmazonSimpleSystemsManagementClient, which is held in a static member.
Web.Config additions
Note: change the assembly/class-name of your builder to match yours, etc.
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="ParameterStore" ssmPrefix="/padnugapp/ApiKeys" type="Microsoft.Configuration.ConfigurationBuilders.AwsSsmConfigBuilder, AspNetWebFormsSample" />
</builders>
</configBuilders>
<appSettings configBuilders="ParameterStore">
<add key="TestKey" value="TestKey Value from web.config" />
<add key="TwitterKey" value="TwitterKey value from web.config" />
</appSettings>
And the AwsSsmConfigBuilder.cs file:
namespace Microsoft.Configuration.ConfigurationBuilders
{
public class AwsSsmConfigBuilder : KeyValueConfigBuilder
{
private string BaseParameterPath = "/padnugapp/ApiKeys";
private static IAmazonSimpleSystemsManagement _client;
static AwsSsmConfigBuilder()
{
_client = new AmazonSimpleSystemsManagementClient();
}
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
if (config["ssmPrefix"] == null)
return;
BaseParameterPath = config["ssmPrefix"];
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
if (_client == null)
return null;
var request = new GetParametersByPathRequest
{
Path = $"{BaseParameterPath}/{prefix}",
WithDecryption = true,
};
var response = _client.GetParametersByPathAsync(request).Result;
var result = response.Parameters.ToDictionary(param => param.Name, param => param.Value, StringComparer.OrdinalIgnoreCase);
return result;
}
public override string GetValue(string key)
{
if (_client == null)
return null;
var request = new GetParameterRequest
{
Name = $"{BaseParameterPath}/{key}",
WithDecryption = true,
};
var response = _client.GetParameterAsync(request).Result;
return response.Parameter.Value;
}
}
}
The code I put into a web-forms (.aspx) page that renders the two appSettings items in HTML:
TestKey =
<%=(System.Configuration.ConfigurationManager.AppSettings["TestKey"]) %>
<br />
TwitterKey =
<%=(System.Configuration.ConfigurationManager.AppSettings["TwitterKey"]) %>
I can't stress enough that this is just for a demo I'm doing, and not tested in any way, shape or form except on my laptop ;-)
I have a website which exposes an ODatas $metadata but to do anything further requires the request to be authenticated (using a cookie).
I want to access this from a console app, not a browser.
I am using Microsofts Odata V4 client code generator.
1) Create a wrapper around the provided Container created by the OData client code generator.
2) Log in and get the cookie you need for authentication
3) Add a hook to the request builder, so you can apply cookies at request time. For my app, I specifically needed the cookie with the name .AspNet.ApplicationCookie
Here is a full working example. You can instantiate this container with the user and password needed as defined at the bottom. This MUST match whatever the controller at the Login API is expecting.
using Nito.AsyncEx;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace MyAppOdataOdataService.Default
{
public class MyAppOdataContainer : Container
{
public Cookie[] _MyAppOdataAuthcookie;
public string cookieAuthName = ".AspNet.ApplicationCookie";
private string baseurl = "https://TheAppwWebsite.co.jp/";
public MyAppOdataContainer(MyAppOdataLoginInfo logininfo ) :
base(new Uri("https://TheAppwWebsite.co.jp/odata/"))
{
// init authorization
_MyAppOdataAuthcookie = AsyncContext.Run(() => AuthenticateUser(logininfo));
if (_MyAppOdataAuthcookie == null) throw new UnauthorizedAccessException();
this.BuildingRequest += AddCookie;
}
private void AddCookie(object sender, Microsoft.OData.Client.BuildingRequestEventArgs e)
{
e.Headers.Add("Cookie", cookieAuthName+"=" + _MyAppOdataAuthcookie.First(c=>c.Name == cookieAuthName).Value);
}
private async Task<Cookie[]> AuthenticateUser(MyAppOdataLoginInfo logininfo)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(baseurl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Uri uri = new Uri(baseurl + "/Login/Login");
HttpResponseMessage response = await client.PostAsJsonAsync(uri, logininfo);
response.EnsureSuccessStatusCode();
// Return the URI of the created resource.
return cookies.GetCookies(uri).Cast<Cookie>().ToArray();
}
}
public class MyAppOdataLoginInfo
{
public string Username { get; set; }
public string Password { get; set; }
}
}
Thanks:
How to apply the cookie:
Creating the client code:
CookieContainer explaination:
Post operation idea here - for authorizing - having to use PostAsJsonAsync
I have an Angular2 app. It is running within ASP.NET 5 (Core).
It makes Http calls to the controller which is working fine.
But now I need to establish Cross Site Scripting projection.
How do I generate a new token on each Http request and then subsequently perform the AntiForgeryToken check in Angular2 apps?
Note: My data forms in Angular are not produced from an MVC view but entirely written in Angular2 and call web services only.
All the examples I have seen are out dated and do not work / do not work fully.
How do I integrate AntiForgeryToken checks in Angular2 against ASP.NET 5 where forms are pure Angular?
Thanks.
A custom action filter is not necessary. It can all be wired up in Startup.cs.
using Microsoft.AspNetCore.Antiforgery;
(...)
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
(...)
}
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
if (context.Request.Path == "/")
{
//send the request token as a JavaScript-readable cookie, and Angular will use it by default
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
return next(context);
});
(...)
}
Then all you need in your controllers is the [ValidateAntiForgeryToken] decorator wherever you want to enforce that a token is provided.
For reference, I found this solution here - AspNet AntiForgery Github Issue 29.
I am using a action filter to send the request tokens.
Simply apply it to the actions you want a new antiforgery token, e.g. Angular2 SPA, WebAPI action, etc.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class AngularAntiForgeryTokenAttribute : ActionFilterAttribute
{
private const string CookieName = "XSRF-TOKEN";
private readonly IAntiforgery antiforgery;
public AngularAntiForgeryTokenAttribute(IAntiforgery antiforgery)
{
this.antiforgery = antiforgery;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
base.OnResultExecuting(context);
if (!context.Cancel)
{
var tokens = antiforgery.GetAndStoreTokens(context.HttpContext);
context.HttpContext.Response.Cookies.Append(
CookieName,
tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
}
}
/* HomeController */
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public IActionResult Index()
{
return View();
}
/* AccountController */
[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
// Send new antiforgery token
[ServiceFilter(typeof(AngularAntiForgeryTokenAttribute), IsReusable = true)]
public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
{
//...
return Json(new { });
}
Register the attribute in Startup, and configure Antiforgery service to read the request token form "X-XSRF-TOKEN" header.
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddScoped<AngularAntiForgeryTokenAttribute>();
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
}
}
I think you need to make custom AntiForgeryValidationToken attribute that supports sending token via header instead of form values. Then add token to header of every request from your Angular2 app to your api. Example here How do you set global custom headers in Angular2?
To validate the token from a header you can use something like this:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException(nameof(filterContext));
}
var httpContext = filterContext.HttpContext;
if (httpContext.Request.Headers["__RequestVerificationToken"] == null)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
httpContext.Response.StatusDescription = "RequestVerificationToken missing.";
filterContext.Result = new JsonResult
{
Data = new { ErrorMessage = httpContext.Response.StatusDescription },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return;
}
var cookie = httpContext.Request.Cookies[System.Web.Helpers.AntiForgeryConfig.CookieName];
System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
Then you just add [ValidateHeaderAntiForgeryToken] on the methods in your controller. Note though, this is from a MVC 5, ASP.NET 4.5.2 project, so you may have to alter it slightly to adjust to .NET Core. Also I modified this to return a JSON result if the token is missing, you can remove that part if you don't handle the error response and output it to the user.
Credits for the core part of this attribute goes to: https://nozzlegear.com/blog/send-and-validate-an-asp-net-antiforgerytoken-as-a-request-header
The hard part is how to generate the AntiForgeryToken without using #Html.AntiForgeryToken() in pure Angular 2 application (without access to .cshtml files). I'm looking for an answer to that as well.
to extend my validation I have created my own model binder based on following article:
http://www.howmvcworks.net/OnModelsAndViewModels/TheBeautyThatIsTheModelBinder
In my application I extend my Person entity like this:
[MetadataType(typeof (PersonMetaData))]
public partial class Person { }
public class PersonMetaData {
[CustomRegularExpression(#"(\w|.)+#(\w|.)+", ErrorMessage = "Email is invalid")]
public string Name;
}
My global.asax looks like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//Change default modelbinding
ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
}
When I call the create event for my PersonController and the provided email is invalid, the ModelState.Valid field is false.
Now I like to create a unit test for the create method:
[TestInitialize()]
public void MyTestInitialize()
{
RegisterRoutes(RouteTable.Routes);
//Change default modelbinding
ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
}
/// <summary>
///A test for Create
///</summary>
// TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
// http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
// whether you are testing a page, web service, or a WCF service.
[TestMethod()]
public void CreateTest()
{
PersonController controller = new PersonController();
Person Person = new Person();
Person.Email = "wrognmail.de
var validationContext = new ValidationContext(Person, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(Person, validationContext, validationResults, true);
foreach (var validationResult in validationResults)
{
controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
}
ActionResult actual;
actual = controller.Create(Person);
// Make sure that our validation found the error!
Assert.IsTrue(controller.ViewData.ModelState.Count == 1, "err.");
}
When I debug the code the ModelState.Valid attribute is telling me that there is no error. I think that the registration of the DefaultBinder was not sucessfull.
How can I register my DefaultBinder in my unit test?
Thank you!
Have a look at this question and Darin's answer. It`s the way to test model binder, might help you.
I am using jQuery ajax to calling a web service method but is is not doing and generating error..
The code is here for jQuery ajax in asp page
var indexNo = 13; //pass the value
$(document).ready(function() {
$("#a1").click(function() {
$.ajax({
type: "POST",
url: "myWebService.asmx/GetNewDownline",
data: "{'indexNo':user_id}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#divResult").text(msg.d);
}
});
});
});
and this is the is web service method
using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Data;
using System.Web.Script.Serialization;
using TC.MLM.DAL;
using TC.MLM.BLL.AS;
/// <summary>
/// Summary description for myWebService
/// </summary>
[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 myWebService : System.Web.Services.WebService
{
public myWebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public string GetNewDownline(string indexNo)
{
IndexDetails indexDtls = new IndexDetails();
indexDtls.IndexNo = "13";
DataSet ds = new DataSet();
ds = TC.MLM.BLL.AS.Index.getIndexDownLineByIndex(indexDtls);
indexNoDownline[] newDownline = new indexNoDownline[ds.Tables[0].Rows.Count];
for (int count = 0; count <= ds.Tables[0].Rows.Count - 1; count++)
{
newDownline[count] = new indexNoDownline();
newDownline[count].adjustedid = ds.Tables[0].Rows[count]["AdjustedID"].ToString();
newDownline[count].name = ds.Tables[0].Rows[count]["name"].ToString();
newDownline[count].structPostion = ds.Tables[0].Rows[count]["Struct_Position"].ToString();
newDownline[count].indexNo = ds.Tables[0].Rows[count]["IndexNo"].ToString();
newDownline[count].promoterId = ds.Tables[0].Rows[count]["PromotorID"].ToString();
newDownline[count].formNo = ds.Tables[0].Rows[count]["FormNo"].ToString();
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
JavaScriptSerializer js = new JavaScriptSerializer();
string resultedDownLine = js.Serialize(newDownline);
return resultedDownLine;
}
public class indexNoDownline
{
public string adjustedid;
public string name;
public string indexNo;
public string structPostion;
public string promoterId;
public string formNo;
}
}
Please help me something.
There is a problem with your input JSON data. Instead of manual serialization you should try to use the builtin JSON class. Ex.
$.ajax({
...
data: JSON.stringify({ indexNo: user_id }),
...
});
This should fix your problem.
You should change the art how you implement serialization in the server. Just add ScriptMethod attribute with ResponseFormat = ResponseFormat.Json. Using of HTTP GET is also possible with respect of additional (optional) attribute UseHttpGet = true
[WebMethod]
[ScriptMethod (UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string GetNewDownline(string indexNo)
The database access can be also improved if you will use SqlConnection, SqlCommand and SqlDataReader classes or another versions of DbDataReader depends of you database source (OleDbDataReader, OracleDataReader, OdbcDataReader, DataTableReader). If you prefer work with strong typed data, then SqlDataAdapter generated by Visual Studio will be better version of DataSet. To do this just add a new Item to your profject, choose "Data" / "DataSet" and then add a Query or TableAdapter.
If you decide to use HTTP GET you should don't make corresponding modification of your web.config file.
<configuration>
<!-- ... -->
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
</protocols>
</webServices>
<!-- ... -->
</system.web>
</configuration>
About usage of JSON.stringify I have the same opinion like "egyedg".
I recommend you to look following links:
Can I return JSON from an .asmx Web Service if the ContentType is not JSON?
How do I build a JSON object to send to an AJAX WebService?
JQuery ajax call to httpget webmethod (c#) not working