write web serice for android with C# - web-services

i want write a web service with C# to call from an android app
in my web service i wrote HElloWorld() method to calles and ConvertDataTableTojSonString to converted data to Json i downloaded converting fonction from internet , my probleim is ConvertDataTableTojSonString function it's return me some thing like
"[{\"ProId\":1,\"ProcName\":\"لبنیات\"},{\"ProId\":2,\"ProcName\":\"لوازم بهداشتی\"},{\"ProId\":3,\"ProcName\":\"لوازم آرایشی\"},{\"ProId\":4,\"ProcName\":\"خشکبار\"},{\"ProId\":5,\"ProcName\":\"نوشیدنی ها\"},{\"ProId\":6,\"ProcName\":\"سبزیجات\"},{\"ProId\":7,\"ProcName\":\"فرآورده های گوشتی\"}]"
the json format that return is not recognizable for my android app i dont need that '/' befor and after items .
any body can help me to find an fanction to change my data table to JSON format for use in android app , thank you : )
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public void HelloWorld() {
JavaScriptSerializer js = new JavaScriptSerializer();
Context.Response.Clear();
Context.Response.ContentType = "application/json";
HelloWorldData data = new HelloWorldData();
data.Message = ConvertDataTableTojSonString(db.Select("select * from ProCategory ",CommandType.Text));
Context.Response.Write(js.Serialize(data.Message));
}
public String ConvertDataTableTojSonString(DataTable dataTable)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer =
new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<String, Object>> tableRows = new List<Dictionary<String, Object>>();
Dictionary<String, Object> row;
foreach (DataRow dr in dataTable.Rows)
{
row = new Dictionary<String, Object>();
foreach (DataColumn col in dataTable.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
tableRows.Add(row);
}
return serializer.Serialize(tableRows);
}

Related

insert whole list of data into sql database table in xamarin.android

i'm trying to create an application where data in a list must be inserted into a database table at once. I made some research and found out that this is possible using user-defined table types where in c# a datatable is used and passed to a stored procedure that is executed. now my problem is that there are no data tables in Xamarin.Android. so I thought to use a list instead. my idea was to create a list in the application and pass it to the webservice method, and in my webservice method I receive the list and convert it to a datatable then pass it as a parameter to the stored procedure. I wrote the following codes:
in my webservice:
[WebMethod]
public bool insrt_dt(List<Class1> lst)
{
SqlParameter param;
SqlConnection conn = new SqlConnection(new DBConnection().ConnectionString);
DataTable dt = list_to_dt(lst);
SqlCommand cmd = new SqlCommand("Insert_Customers", conn);
cmd.CommandType = CommandType.StoredProcedure;
if (conn.State == System.Data.ConnectionState.Closed)
{
conn.Open();
}
param = new SqlParameter("#tblcustomers", dt);
param.Direction = ParameterDirection.Input;
param.DbType = DbType.String;
cmd.Parameters.Add(param);
cmd.CommandTimeout = 300;
int a=cmd.ExecuteNonQuery();
if (a > 0)
{
return true;
}
else return false;
}
}
Class1:
public class Class1
{
public int id { get; set; }
public string name { get; set; }
public string country { get; set; }
}
in my Xamarin.Android app
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button btn = FindViewById<Button>(Resource.Id.button1);
btn.Click += delegate
{
wr.WebService1 ws = new wr.WebService1();
wr.Class1 class1 = new wr.Class1();
List<wr.Class1> lst = new List<wr.Class1>(){
new wr.Class1() { id = 1, name = "hgf", country = "khg" },
new wr.Class1() { id = 2, name = "hgf", country = "khg"} };
ws.insrt_dt(lst);
ws.insrt_dtCompleted += Ws_insrt_dtCompleted;
};
}
private void Ws_insrt_dtCompleted(object sender, wr.insrt_dtCompletedEventArgs e)
{
bool l = e.Result;
if (l == true)
Toast.MakeText(this, "khh", ToastLength.Long).Show();
else
Toast.MakeText(this, "ijo'pioo", ToastLength.Long).Show();
}
}
but I keep getting this error:
Argument 1: cannot convert from 'System.Collections.Generic.List<app_dt.wr.Class1>' to 'app_dt.wr.Class1[]
so I used these lines instead
new wr.Class1() { id = 1, name = "hgf", country = "khg" },
new wr.Class1() { id = 2, name = "hgf", country = "khg"} };
wr.Class1[] class1s = lst.ToArray();
ws.insrt_dt(class1s);
now I don't get an error, but it doesn't work, I mean why does it say that the webservice method input must be an array and I've created it as a list. any suggestions for this?
As i know, Xamarin do not support System.Data.SqlClient. If you want to use the database for the Xamarin android project, you could use the SQLite.NET.
Install the package from the NuGet.
NuGet: sqlite-net-pcl https://www.nuget.org/packages/sqlite-net-pcl/
For the code sample about how to use the database in Xamarin, you could check the link below. https://learn.microsoft.com/en-us/xamarin/get-started/quickstarts/database?pivots=windows
For Xamarin.Android, you could check the sample code in the link below. https://learn.microsoft.com/en-us/xamarin/android/data-cloud/data-access/using-sqlite-orm

Connect to Azure Text Analytics from Console App without await

I am trying to call an Azure API (Text Analytics API) from a C# console application with a HttpRequest and I do not want to use any DLLs or await
but using the below snippet I am receiving "Bad Request". Can someone help me where it is going wrong.
public static void ProcessText()
{
string apiKey = "KEY FROM AZURE";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = "https://eastus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment?" + queryString;
//HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("I really love Azure. It is the best cloud platform");
using (var content = new ByteArrayContent(byteData))
{
//content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(requestUri, content).Result;
Console.WriteLine(response);
Console.ReadLine();
}
}
string apiKey = "<<Key from Azure>>";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = "https://**eastus**.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment?" + queryString;
//HttpResponseMessage response;
var body = new
{
documents = new[]
{
new
{
ID="1", text="I really love Azure. It is the best cloud platform"
}
}
};
string json = JsonConvert.SerializeObject(body);
byte[] byteData = Encoding.UTF8.GetBytes(json);
dynamic item = null;
using (var con = new ByteArrayContent(byteData))
{
//content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(requestUri, con).Result;
if (response.StatusCode == HttpStatusCode.OK)
{
string res = string.Empty;
using (HttpContent content = response.Content)
{
Task<string> result = content.ReadAsStringAsync();
res = result.Result;
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
item = serializer.Deserialize<object>(res);
}
}
Hi All, I could able to get the API output using the above approach

Can not pass a list of strings to a Web API endpoint. Why?

Can not pass a list of strings to a Web API endpoint. Why?
Here is my controller:
[Route("[controller]")]
[ApiController]
public class MyController
{
[HttpPost("foo")]
public string MyMethod(List<string> strs)
{
return "foo";
}
}
Here is how I am trying to call it:
var strs = new List<string> { "bar" };
var json = JsonConvert.SerializeObject(strs);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpCliet.PostAsync("/My/foo", content);
Before calling the endpoint I place a breakpoint on the return "foo"; line. Once the breakpoint is hit the strs list inside the MyController.MyMethod is empty. The strs is not null, but it contains no elements. While my intentions and expectations are to see the strs containing one element, i.e. the string "bar".
I am using the ASP.NET Core 2.2 in project where I create and use the HttpClient. And I am using the same ASP.NET Core 2.2 in project where I have the endpoint.
I am not sure what is wrong here. I have checked a few sources. E.g. the following:
C# HTTP post , how to post with List<XX> parameter?
https://carldesouza.com/httpclient-getasync-postasync-sendasync-c/
https://blog.jayway.com/2012/03/13/httpclient-makes-get-and-post-very-simple/
And I can not find what I am missing according to those resources.
UPDATE
The following call works for me as expected:
var json = JsonConvert.SerializeObject(string.Empty);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await server.CreateClient().PostAsync("/My/foo?strs=bar", content);
Maybe someone knows why the parameters in my case are read from the query string only, but not from body?
You can change your url to a full url in client.PostAsync.Here is a demo worked:
Api(localhost:44379):
WeatherForecastController:
[HttpPost("foo")]
public string MyMethod(List<string> strs)
{
return "foo";
}
Call(localhost:44326):
public async Task<IActionResult> CheckAsync() {
HttpClient client = new HttpClient();
var strs = new List<string> { "bar","bar1","bar2" };
var json = JsonConvert.SerializeObject(strs);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://localhost:44379/WeatherForecast/foo", content);
return Ok(response);
}
result:

Using Httpclient for send SOAP request In Asp.net Core

Im using Asp.net Core, for calling an asmx service which has 4 methods and i want to call one of them by the name: Verify method, i do this steps:
1-Create realted SOAP:
private XmlDocument CreateSoapEnvelope(PayVM payModel)
{
XmlDocument soapEnvelop = new XmlDocument();
string requiredXML = string.Format(#"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/1999/XMLSchema""><SOAP-ENV:Body><verifyTransaction xmlns=""http://tempuri.org/""> <String_1 xsi:type=""xsd:string"">{0}</String_1><String_2 xsi:type=""xsd:string"">{1}</String_2></verifyTransaction></SOAP-ENV:Body></SOAP-ENV:Envelope>", payModel.ReNO, payModel.MID);
soapEnvelop.LoadXml(requiredXML);
return soapEnvelop;
}
2-create the HttpClient and send my request:
XmlDocument soapRequest = CreateSoapEnvelope(iPGVerifyResultModel);
using (var client = new HttpClient())
{
var request = new HttpRequestMessage()
{
RequestUri = new Uri("relatedUri/ServiceName.asmx"),
Method = HttpMethod.Post
};
request.Content = new StringContent(soapRequest.ToString(), Encoding.UTF8, "text/xml");
request.Headers.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
request.Headers.Add("SOAPAction", "Verify"); //I want to call this method
HttpResponseMessage response = client.SendAsync(request).Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception();
}
Task<Stream> streamTask = response.Content.ReadAsStreamAsync();
Stream stream = streamTask.Result;
var sr = new StreamReader(stream);
var soapResponse = XDocument.Load(sr);
//do some other stuff...
}
but i didn't result, i try uses service by same parameters with Soap UI and the service work properly, but in my way i got StatusCode: 400 what is the problem?

Unit testing post controller .NET Web Api

I don't have much experience with .NET Web Api, but i've been working with it a while now, following John Papa's SPA application tutorial on Pluralsight. The application works fine, but the thing i'm struggling with now, is unit testing POST-controllers.
I have followed this incredible guide on how to unit test web api controllers. The only problem for me is when it comes to test the POST method.
My controller looks like this:
[ActionName("course")]
public HttpResponseMessage Post(Course course)
{
if (course == null)
throw new HttpResponseException(HttpStatusCode.NotAcceptable);
try
{
Uow.Courses.Add(course);
Uow.commit();
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var response = Request.CreateResponse(HttpStatusCode.Created, course);
string uri = Url.Link(routeName: "ControllerActionAndId",
routeValues: new { id = course.Id });
response.Headers.Location = new Uri(uri);
return response;
}
And my unit test looks like this:
[Test]
public void PostShouldReturnHttpResponse()
{
var populatedPostController = new CoursesController(new TestUOW());
SetupPostControllerForTest(populatedPostController);
var course = new Course
{
Id = 12,
Author = new UserProfile()
{
Firstname = "John",
Lastname = "Johnson",
},
Description = "Testcourse",
Title = "Test Title"
};
var responses = populatedPostController.Post(course);
ObjectContent content = responses.Content as ObjectContent;
Course result = (Course)content.Value;
Assert.AreSame(result, course);
}
With the help function:
public static void SetupPostControllerForTest(ApiController controller)
{
var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/courses/course");
var route = config.Routes.MapHttpRoute(
name: "ControllerActionAndId",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { id = #"^\d+$" }
);
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "courses" }, { "action", "course" } });
controller.ControllerContext = new HttpControllerContext(config, routeData, request);
controller.Request = request;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
}
When i debug the unit test, it seems to fail at:
string uri = Url.Link(routeName: "ControllerActionAndId",
routeValues: new { id = course.Id });
response.Headers.Location = new Uri(uri); //Exception because uri = null
It seems like the Url.Link can't find the route.
I tried this guide aswell, but i really want the example i have above to work.
Am i missing something really basic here?
Yes, you are missing the one line in the configuration as Nemesv mentioned.
controller.Request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData
As you can see, configuring a controller just for using the UrlHelper is extremely complex. I tend to avoid the use of UrlHelper in the controller classes for that reason. I usually introduce an external dependency to make testing easier like an IUrlHelper, which allows me to mock the behavior in an unit test.
public interface IUrlHelper
{
string Link(string routeName, object routeValues);
string Route(string routeName, object routeValues);
}
public class UrlHelperWrapper : IUrlHelper
{
UrlHelper helper;
public UrlHelperWrapper(UrlHelper helper)
{
this.helper = helper;
}
public string Link(string routeName, object routeValues)
{
return this.helper.Link(routeName, routeValues);
}
public string Route(string routeName, object routeValues)
{
return this.helper.Route(routeName, routeValues);
}
}
I inject this UrlHelperWraper in the real Web API, and a mock of the IUrlHelper interface in the tests. By doing that, you don't need all that complex configuration with the routes.
Regards,
Pablo.