Azure Functions (AF) 3.0/.NET 5.0/XUnit Unit Testing - Compilation Errors (C#) - unit-testing

I am trying to adapt the Microsoft example for AF 3.0/.NET Core 3.1/xUnit (see Strategies for testing your code in Azure Functions) to work with AF 3.0/.NET 5.0/xUnit. However, I am running into compilation issues.
The Azure Function is a simple HTTP Trigger (GET only), ExportFuncApp.csproj file is as follows:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.12" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.2.0" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.2" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
The ExportFunc.cs file is as follows:
using System.Net;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
namespace ExportFuncApp
{
public class ExportFunc
{
[Function(nameof(ExportFunc))]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger("ExportFunc");
logger.LogInformation("C# HTTP trigger function processed a request.");
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
}
}
Nothing special there. However, XUnit tests provided by Microsoft (.NET Core 3.1) are not really applicable to .NET 5.0. There was a StackOverflow article on the subject: Testing an Azure Function in .NET 5. 4 solutions were given in the article and all of them have compile issues. The first solution given was (ExportFuncUnitTests2.cs):
using Xunit;
using ExportFuncApp;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using Moq;
using Microsoft.Azure.Functions.Worker;
using System.Net;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker.Http;
namespace ExportFuncAppUnitTestsXunit
{
public class ExportFuncUnitTests2
{
[Fact]
public async Task Http_trigger_should_return_known_string()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<ILoggerFactory, LoggerFactory>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var context = new Mock<FunctionContext>();
context.SetupProperty(c => c.InstanceServices, serviceProvider);
var byteArray = Encoding.ASCII.GetBytes("test");
var bodyStream = new MemoryStream(byteArray);
var request = new Mock<HttpRequestData>(context.Object);
request.Setup(r => r.Body).Returns(bodyStream);
request.Setup(r => r.CreateResponse()).Returns(() =>
{
var response = new Mock<HttpResponseData>(context.Object);
response.SetupProperty(r => r.Headers, new HttpHeadersCollection());
response.SetupProperty(r => r.StatusCode);
response.SetupProperty(r => r.Body, new MemoryStream());
return response.Object;
});
var result = await ExportFunc.Run(request.Object, context.Object);
result.HttpResponse.Body.Seek(0, SeekOrigin.Begin);
// Assert
var reader = new StreamReader(result.HttpResponse.Body);
var responseBody = await reader.ReadToEndAsync();
Assert.NotNull(result);
Assert.Equal(HttpStatusCode.OK, result.HttpResponse.StatusCode);
Assert.Equal("Hello test", responseBody);
}
}
}
This results in a compilation error in ExportFuncUnitTests2.cs:
CS1061 'HttpResponseData' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'HttpResponseData' could be found (are you missing a using directive or an assembly reference?)
for:
var result = await ExportFunc.Run(request.Object, context.Object);
The second solution given in the article involves FakeHttpRequestData.cs:
using System;
using System.Collections.Generic;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.Functions.Worker;
using System.IO;
using System.Security.Claims;
namespace ExportFuncAppUnitTestsXunit
{
class FakeHttpRequestData : HttpRequestData
{
public FakeHttpRequestData(FunctionContext functionContext, Uri url, Stream body = null) : base(functionContext)
{
Url = url;
Body = body ?? new MemoryStream();
}
public override Stream Body { get; } = new MemoryStream();
public override HttpHeadersCollection Headers { get; } = new HttpHeadersCollection();
public override IReadOnlyCollection<IHttpCookie> Cookies { get; }
public override Uri Url { get; }
public override IEnumerable<ClaimsIdentity> Identities { get; }
public override string Method { get; }
public override HttpResponseData CreateResponse()
{
return new FakeHttpResponseData(FunctionContext);
}
}
}
and, FakeHttpResponseData.cs:
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.Functions.Worker;
using System.Net;
using System.IO;
namespace ExportFuncAppUnitTestsXunit
{
class FakeHttpResponseData : HttpResponseData
{
public FakeHttpResponseData(FunctionContext functionContext) : base(functionContext)
{
}
public override HttpStatusCode StatusCode { get; set; }
public override HttpHeadersCollection Headers { get; set; } = new HttpHeadersCollection();
public override Stream Body { get; set; } = new MemoryStream();
public override HttpCookies Cookies { get; }
}
}
And the test is (ExportFuncUnitTests2.cs):
using Xunit;
using ExportFuncApp;
using System.Threading.Tasks;
using System.IO;
using System.Text;
using Moq;
using Microsoft.Azure.Functions.Worker;
using System;
using System.Net;
using Microsoft.Extensions.Logging.Abstractions;
namespace ExportFuncAppUnitTestsXunit
{
public class ExportFuncUnitTests2
{
[Fact]
public async Task Http_trigger_should_return_known_string()
{
// Arrange
var body = new MemoryStream(Encoding.ASCII.GetBytes("{ \"test\": true }"));
var context = new Mock<FunctionContext>();
var request = new FakeHttpRequestData(
context.Object,
new Uri("https://stackoverflow.com"),
body);
// Act
var function = new ExportFunc(new NullLogger<ExportFunc>());
var result = await function.Run(request, context);
result.HttpResponse.Body.Position = 0;
// Assert
var reader = new StreamReader(result.HttpResponse.Body);
var responseBody = await reader.ReadToEndAsync();
Assert.NotNull(result);
Assert.Equal(HttpStatusCode.OK, result.HttpResponse.StatusCode);
Assert.Equal("Hello test", responseBody);
}
}
}
The ExportFuncUnitTests2.cs has the following compilation errors:
CS1729 'ExportFunc' does not contain a constructor that takes 1 arguments
for:
var function = new ExportFunc(new NullLogger<ExportFunc>());
and
CS1503 Argument 2: cannot convert from 'Moq.Mock<Microsoft.Azure.Functions.Worker.FunctionContext>' to 'Microsoft.Azure.Functions.Worker.FunctionContext'
for:
var result = await function.Run(request, context);
I the article Guide for running C# Azure Functions in an isolated process was somewhat useful but no help in terms of unit testing. Maybe I am missing the point. Since there is no examples/documentation on how to do unit testing for AF 3.0 with .NET 5.0 from Microsoft then I should not be trying to do that?
Any pointers will be greatly appreciated. Thanks!

Your Run() function in ExportFunc is not awaitable. Therefore, you should replace the line:
var result = await function.Run(request, context)
with:
var result = function.Run(request, context).
If you want to test an awaitable function (i.e., async Run()), then you'd call it from your Unit Test with await.

Related

asp.net core 6.0 web api unit test using NUnit

I am trying to create the simple web api test for the controller action method I have in my project. I already create and add the test project in my solution. And add the Nunit nuget package in test project.
The controller I am trying to test is look like this:
[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IHostEnvironment _hostEnvironment;
private readonly ILogger<HomeController> _logger;
private BaseDataAccess _datatAccess = new BaseDataAccess()
public HomeController(ILogger<HomeController> logger, IConfiguration configuration, IHostEnvironment hostEnvironment)
{
_logger = logger;
_configuration = configuration;
_hostEnvironment = hostEnvironment;
}
[HttpGet("GetInfo/{code}")]
public IActionResult GetInfo(string code)
{
List<InfoModel> infos = new List<InfoModel>();
int isNumber;
if (String.IsNullOrEmpty(code) || !int.TryParse(code, out isNumber))
{
_logger.LogInformation(String.Format("The code pass as arguments to api is : {0}", code));
return BadRequest("Invalid code");
}
try
{
_logger.LogDebug(1, "The code passed is" + code);
SqlConnection connection = _datatAccess.GetConnection(_configuration, _hostEnvironment);
string sql = string.Format ("SELECT * from table1 where code={0}", code);
DataTable dt = _datatAccess.ExecuteQuery(connection,CommandType.Text, sql);
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
infos.Add(new InfoModel
{
ID = dr["id"].ToString(),
code = dr["code"].ToString()
});
}
}
}
catch (Exception ex)
{
_logger.LogError(4, String.Format("Error Message: " + ex.Message + "\n" + ex.StackTrace));
return BadRequest("There is something wrong.Please contact the administration.");
}
return new OkObjectResult(infos);
}
}
Now when I try to create the unit test I need to pass the configuration, hostenvironment and logger to HomeController from my TestHomeController. And I don't know how to instantiate these settings and pass to controller:
using NUnit.Framework;
using Microsoft.AspNetCore.Mvc;
using MyApi.Models;
using MyApi.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace MyApi.Tests
{
[TestFixture]
public class TestHomeController: ControllerBase
{
private readonly IConfiguration _configuration; //How to instantiate this so it is not null
private readonly IHostEnvironment _hostEnvironment ;//How to instantiate this so it is not null
private ILogger<HomeController> _logger;//How to instantiate this so it is not null
[Test]
public void GetInfo_ShouldReturnAllInfo()
{
var controller = new HomeConteoller(_logger, _configuration, _hostEnvironment);
var result = controller.GetInfo("11");
var okObjectResult = (OkObjectResult)result;
//Assert
okObjectResult.StatusCode.Equals(200);
}
}
}
Thanks for any help and suggestions.
Probably, you have startup.cs. Don't you?
if you gonna test a controller, then you need to build a whole instance of an application. Here I put an example of how you can test your code if you have Startup.cs.
public class SUTFactory : WebApplicationFactory<Startup>
{
protected override IHostBuilder CreateHostBuilder()
{
return Program.CreateHostBuilder(null);
}
}
public class TestControllerTests
{
private SUTFactory factory;
private HttpClient _client;
public TestControllerTests()
{
factory = new SUTFactory();
_client = factory.CreateClient();
}
[Test]
public async Task GetPatientInterviewID_ShouldReturnAllInterviewID()
{
// Arrange
var id = "11";
// Act
var result = await _client.GetAsync($"Home/GetInfo/{id}");
// Assert
Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
}
}
This example is closer to Integration testing rather than Unit-testing. If you want to have unit-test then you need to do the following things
BaseDataAccess _datatAccess this is a specific realization and it cannot be mocked (comparing to ILogger, IHostEnvironment etc)
move all your code from the controller to a separate class, and test this class.

Integrated Unit Testing is not running in ASP.NET core MVC/Web API

I am developing a web API using ASP.Net core. I am doing integrated testing to my project. I am following this link, https://koukia.ca/integration-testing-in-asp-net-core-2-0-51d14ede3968. This is my code.
I have the controller to be tested in the thegoodyard.api project.
namespace thegoodyard.api.Controllers
{
[Produces("application/json")]
[Route("api/category")]
public class CategoryController: Controller
{
[HttpGet("details/{id}")]
public string GetCategory(int id = 0)
{
return "This is the message: " + id.ToString();
}
}
}
I added a new unit test project called thegoodyard.tests to the solution. I added a TestServerFixture class with the following definition
namespace thegoodyard.tests
{
public class TestServerFixture : IDisposable
{
private readonly TestServer _testServer;
public HttpClient Client { get; }
public TestServerFixture()
{
var builder = new WebHostBuilder()
.UseContentRoot(GetContentRootPath())
.UseEnvironment("Development")
.UseStartup<Startup>(); // Uses Start up class from your API Host project to configure the test server
_testServer = new TestServer(builder);
Client = _testServer.CreateClient();
}
private string GetContentRootPath()
{
var testProjectPath = PlatformServices.Default.Application.ApplicationBasePath;
var relativePathToHostProject = #"..\..\..\..\..\..\thegoodyard.api";
return Path.Combine(testProjectPath, relativePathToHostProject);
}
public void Dispose()
{
Client.Dispose();
_testServer.Dispose();
}
}
}
Then again in the test project, I created a new class called, CategoryControllerTests with the following definition.
namespace thegoodyard.tests
{
public class CategoryControllerTests: IClassFixture<TestServerFixture>
{
private readonly TestServerFixture _fixture;
public CategoryControllerTests(TestServerFixture fixture)
{
_fixture = fixture;
}
[Fact]
public async Task GetCategoryDetai()
{
var response = await _fixture.Client.GetAsync("api/category/details/3");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
bool containMessage = false; //responseString.Contains("This is the message: 3"); - I commented on purpose to make the test fails.
Assert.True(containMessage);
}
}
}
Then I right on the test method and clicked run tests in the option to run the test. But none of the tests was run. This is the output.
What is missing in my code? How can I get my integrated test running?
Please check following NuGet packages in your project:
Microsoft.AspNetCore.TestHost
Microsoft.NET.Test.Sdk
xunit
xunit.runner.visualstudio
Perhaps there's a build error that's preventing the project from being compiled. There's really not enough information here to say for sure. Rebuild your solution, and ensure there's no errors.
Aside from that, you can remove some variables by reducing the test code needed. ASP.NET Core includes a WebApplicationFactory<TEntryPoint> fixture out of the box for bootstrapping a test server. You can therefore change your test code to just:
public class CategoryControllerTests: IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public CategoryControllerTests(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
[Fact]
public async Task GetCategoryDetail()
{
var client = _factory.CreateClient();
var response = await client.GetAsync("api/category/details/3");
...
See the documentation for additional information and more advanced scenarios.
This way works fine for xUnit based intergration tests, which use Startup configuration. the code blow also demonstrates how to override some settings in appSetting.json to specific values for testing, as well as how to access to DI services.
using System;
using System.Net.Http;
using MyNamespace.Web;
using MyNamespace.Services;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace MyNamespace.Tests
{
public class TestServerDependent : IDisposable
{
private readonly TestServerFixture _fixture;
public TestServer TestServer => _fixture.Server;
public HttpClient Client => _fixture.Client;
public TestServerDependent()
{
_fixture = new TestServerFixture();
var myService = GetService<IMyService>();
// myService.PerformAnyPreparationsForTests();
}
protected TService GetService<TService>()
where TService : class
{
return _fixture.GetService<TService>();
}
public void Dispose()
{
_fixture?.Dispose();
}
}
public class TestServerFixture : IDisposable
{
public TestServer Server { get; }
public HttpClient Client { get; }
public TestServerFixture()
{
var hostBuilder = WebHost.CreateDefaultBuilder()
.ConfigureAppConfiguration(
(builderContext, config) =>
{
var env = builderContext.HostingEnvironment;
config
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.Testing.json", optional: false,
reloadOnChange: true);
})
.ConfigureLogging(
(hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseStartup<Startup>();
Server = new TestServer(hostBuilder);
Client = Server.CreateClient();
}
public void Dispose()
{
Server.Dispose();
Client.Dispose();
}
public TService GetService<TService>()
where TService : class
{
return Server?.Host?.Services?.GetService(typeof(TService)) as TService;
}
}
}
How the simple integration test might look like with the described above:
using System.Net;
using Xunit;
namespace MyNamespace.Tests
{
public class SimpleIntegrationTest : TestServerDependent
{
[Fact]
public void RedirectToLoginPage()
{
var httpResponseMessage = Client.GetAsync("/").Result;
// Smoke test to make sure you are redirected (to Login page for instance)
Assert.Equal(HttpStatusCode.Redirect, httpResponseMessage.StatusCode);
}
}
}

How do I perform integration test on WebApi controller using FakeItEasy?

I am new at implementing unit tests and integration tests. I am trying to write some integration tests for my application.
Following are the code snippets from my application to give you all the idea of my code.
It would be great help if you could provide me some guidance for it.
namespace MyApplication.ApiControllers
{
[Authorize]
[RoutePrefix("api/customers")]
[AppExceptionFilter]
public class CustomersController : ApiController
{
private readonly IMediator _mediator;
public CustomersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
[Route("GetCustomer")]
public async Task<IHttpActionResult> GetCustomer(string customerNumber, string customerType = null)
{
var result = await _mediator.RequestAsync(new GetCustomerRequest(customerNumber, customerType));
return Ok(result);
}
}
}
Following is the implementation for GetCustomerRequest handler
public async Task<List<Customer>> HandleAsync(GetCustomerRequest request)
{
var result = await customerService.GetCustomer(request.CustomerNumber, request.CustomerType);
// some business logic
return result;
}
Following is the implementation for customerService
public async Task<List<Customer>> GetCustomer(string customerNumber, string customerType = null)
{
using (var dataContext = _dataContextFactory.Invoke())
{
result = await dataContext.Customers
.Where(b => b.CustomerNumber == customerNumber)
.Where(b => b.CustomerType == customerType)
.Select(b => new Customer
{
// Properties assignment...
})
.ToListAsync();
}
return result;
}
Below is the integration unit test what I have tried.
namespace MyApplication.Tests.Integrations
{
[TestFixture]
public class CustomersControllerTests
{
private string _baseAddress;
private string _username;
private string _password;
private IApiClient _apiClient;
[SetUp]
public void Setup()
{
_baseAddress = "https://mywebaaplication.com"; // TODO get this from a config
_username = "";
_password = "";
_apiClient = new ApiClient(new ApiClientAuthenticationHandler(), _baseAddress); // REPLACE with AzureADApiClientAuthenticationHandler
}
[Test]
public async Task CustomersController_GetCustomer()
{
var customerNumber = string.Empty;
var customerType = 500;
var result = await _apiClient.GetAsync<Customer[]>($"/api/customers/GetCustomer?customerNumber={customerNumber}&customerType={customerType}");
Assert.IsNotNull(result);
Assert.IsTrue(result?.Length > 0);
}
}
}
You can do a few things:
Create a webhost within your unit test, then do http requests against it
Not test your controller in a unit test, but in a liveness/readiness check (because it's just glue code anyway). Just do integration testing for your service.
Just test against "new CustomersController"
There isn't a right/wrong answer here. You just look at the risks, and test accordingly. Also depends on the type of code-changes you expect. Sometimes its fine to create the test only within the context of a new change, no need to anticipate everything.

Orchard CMS WCF Service with ServiceRoute

I have configured a Orchard module to expose a service and have enabled it. I cannot work out the URL to use based on the following.
Routes.cs
namespace OrchardRestService
{
using System.Collections.Generic;
using System.ServiceModel.Activation;
using Orchard.Mvc.Routes;
using Orchard.Wcf;
public class Routes : IRouteProvider
{
#region Implementation of IRouteProvider
public IEnumerable<RouteDescriptor> GetRoutes()
{
return new[] {
new RouteDescriptor {
Priority = 20,
Route = new ServiceRoute(
"ContentService",
new OrchardServiceHostFactory(),
typeof(IContentService))
}
};
}
public void GetRoutes(ICollection<RouteDescriptor> routes)
{
foreach (var routeDescriptor in GetRoutes())
routes.Add(routeDescriptor);
}
#endregion
}
}
IContentService.cs:
namespace OrchardRestService
{
using System.ServiceModel;
using Orchard;
[ServiceContract]
public interface IContentService : IDependency
{
[OperationContract]
ContentResult GetContent(string contentPath);
}
}
ContentService.cs:
namespace OrchardRestService
{
using System.Collections.Generic;
using System.ServiceModel.Activation;
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ContentService : IContentService
{
public ContentResult GetContent(string contentPath)
{
var contentResult = new ContentResult
{ ContentValues = new Dictionary<string, string>(), Found = true, Path = contentPath };
return contentResult;
}
}
}
I've tried to follow what Bertrand Le Roy has written here and here but seem to be missing something.
My code is .Net 4 by the way so no need for an SVC file.
Closing as I'd be jumping through hoops to use N2 in this way rather than what it is designed for.

Web service method is not accessible from jQuery ajax

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