Xamarin form consume asmx web service - xamarin

I have a xamarin form apps and I need it to consume an asmx web service. I encounter error when creating class in Android platform to implement the interface.
I have following this tutorial (https://www.c-sharpcorner.com/article/consuming-asmx-services-in-xamarin-forms/) to consume the asmx web service. I have this web method called "GetAllProjects" which will return List. I keep encounter error for the line of code:
"return new List(result);" (refer to the codes below).
Error message: Error CS1503 Argument 1: cannot convert from 'IMSr2.Droid.IMSWS.Project[]' to 'int'. How should I return the result from the web service?
public async Task<List<IProject>> GetAllProjects(string criteria = null)
{
return await Task.Run(() =>
{
var result = service.GetAllProjects();
return new List<IProject>(result);
/* How should I return the result from the web service?*/
});
}
/* This hello world is working*/
public Task<string> HelloWorld()
{
return Task.Run(() =>
{
return service.HelloWorld();
});
}
I am expecting the same result as the tutorial: https://www.c-sharpcorner.com/article/consuming-asmx-services-in-xamarin-forms/
I need to return the result from the webservice call ("GetAllProjects") and display in the listview.
Appreciate for help.

If you check the error statement correctly it says IMSr2.Droid.IMSWS.Project[]' to 'int' which clearly means that the method of your Service object by the name of getallprojects returns int
i.e.
service.GetAllProjects();
Is returning int when it should be returning Project[].
Check return type for GetAllProjects

Related

Wep API to take multiple parameters

I am new to web api. I created a sample web api and it works fine to return all data from a table and by Id. Right now I am trying to create a function to take multiple parameters but I get errors with "HTTP Error 404.0 - Not Found". Below is my code and I have no clue where the problem is:
enter code here
// GET: api/Biosample
// http://localhost:53205/api/Biosample/example1/catalognbr/campusstr/
[Route("example1/{catalognbr}/{campusstr}")]
[HttpGet]
public IQueryable<Biosample> GetBiosample(float catalognbr, string campusstr)
{
var Biosample= (from a in db.Biosample
where a.CATALOG_NBR == catalognbr &&
a.CAMPUS_NAME.Contains(campusstr)
select a
);
return Biosample;
}

Internal Server Error (500) when creating a document in DocumentDB from data passed on from Console Application to ASP.NET WebAPI

I have an ASP.NET WebAPI Controller which creates a document in Azure DocumentDB from the data passed on to its POST method from a Console app. The return type of the POST method is HttpResponseMessage which returns a status code for OK (i.e. 200) when the document has been successfully created.
The document gets created successfully from the WebAPI and the status code 200 is returned too. But somewhere then it goes wrong (which I can't figure out where and why) and the status code that my Console app receives after the successful POST is 500 - an Internal Server Error occurred.
public HttpResponseMessage Post([FromBody]GPSDataVM data)
{
if (KeyRepository.IsValid(data.Key))
{
// Creates a document in DocumentDB by calling an async method CreateLiveDataDocument(data);
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
Can anyone help me out with the situation? Thanks in advance ..
I found an answer to my problem from the following address:
Web Api + HttpClient: An asynchronous module or handler completed while an asynchronous operation was still pending
I changed the definition to my WebAPI Controller to:
public **async Task<HttpResponseMessage>** Post([FromBody]GPSDataVM data) {
if (KeyRepository.IsValid(data.Key))
{
// Creates a document in DocumentDB by calling an async method
**// Code for CreateLiveDataDocument(data)**
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.Unauthorized); }

Calling an ASP.Net RESTful POST controller API method with HTTPClient.PostAsync

A colleague has written an Azure Mobile Service API which includes the following controller method:
public class SegmentationController : ApiController
{
// [...]
// POST api/<controller>/id
public async Task<string> Post(string id)
{
// [...]
I am trying to call that from a Windows Universal app. The calls to GET methods work without issue but I am failing to call that POST method. Here is what I've tried:
response = await client.PostAsync("api/segmentation/", new StringContent(item.Id));
// 405 Method Not Allowed
response = await client.PostAsync("api/segmentation/" + item.Id, new StringContent(""));
// 500 Internal Server Error
response = await client.PostAsync("api/segmentation/", new StringContent("id=" + item.Id));
// 405 Method Not Allowed
response = await client.PostAsync("api/segmentation/", new StringContent("{\"id\":" + item.Id + "}"));
// 405 Method Not Allowed
(N.B. System.Collections.Specialized.NameValueCollection used in Marc's answer is not available on WinRT / Windows Universal.)
It is possible that my second call is correct and that the error is in the server side code; we are exploring that possibility.
What is the correct way to make a POST call to an ASP.Net RESTful API method which expects a parameter called "id" of type string?
Your parameter is the problem. You have two options:
Use a query parameter instead of body. e.g. api/segmentation?id=abc
Add [FromBody] Attribute to your parameter. e.g. public async Task<string> Post([FromBody]string id)
Now your parameter is read from body. by default only complex types are read from body.
For more details see Parameter Binding in ASP.NET Web API
It was a server error. Once we had added error reporting code we could see that the problem was the server failing to load a C++ DLL it relied on due to an x64 /x86 mismatch on Azure. The call style that now works is the second one I list in the question:
response = await client.PostAsync("api/segmentation/" + item.Id, new StringContent(""));

WebApi Odata Windows Store App EndSaveChanges exception

I am trying to create a Windows Store App using a WebApi Odata controller. After some effort I have all the Get requests working, I am now moving onto the CRUD methods, and am getting the following Exception on the EndSaveChanges of the Data Service Context.
<?xml version="1.0" encoding="utf-8"?>
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code />
<m:message xml:lang="en-US">No HTTP resource was found that matches the request URI 'http://localhost:56317/odata/ESFClients(guid'f04ad636-f896-4de4-816c-388106cd39ce')'.</m:message>
<m:innererror>
<m:message>No routing convention was found to select an action for the OData path with template '~/entityset/key'.</m:message>
<m:type></m:type>
<m:stacktrace></m:stacktrace>
</m:innererror>
</m:error>
Now I think this is a bug in WebApi from this http://aspnetwebstack.codeplex.com/workitem/822 and its hiding the actual error. To make sure it wasn't my Odata Endpoint I created a quick console app to get an entry, update it and Patch it back, which worked all ok. My WebApi Odata Controller derives from ODataController with
public HttpResponseMessage Patch([FromODataUri] Guid key, Delta<ESFClient> patch)
As the method.
In my windows application I have a extension method on the DataServiceContext for the Save Changes.
public static async Task<DataServiceResponse> SaveChangesAsync(this DataServiceContext context, SaveChangesOptions options)
{
var queryTask = Task.Factory.FromAsync<DataServiceResponse>(context.BeginSaveChanges(options, null, null),
queryAsyncResult =>
{
var results = context.EndSaveChanges(queryAsyncResult);
return results;
});
return await queryTask;
}
And calling the update like so from a blank Windows Store XAML page.
public async Task UpdateWeekNo()
{
var container = new ESFOdataService.Container(new Uri("http://localhost:56317/odata/"));
var clients = (DataServiceQuery<ESFClient>)from p in container.ESFClients where p.UserID == new Guid("f04ad636-f896-4de4-816c-388106cd39ce") select p;
var result = await clients.ExecuteAsync();
var updatedClient = result.Single();
if (updatedClient != null)
{
updatedClient.WeekNo = 19;
container.UpdateObject(updatedClient);
await container.SaveChangesAsync(SaveChangesOptions.PatchOnUpdate); // Use PATCH not MERGE.
}
}
So does anyone come across the same issue, or know how I can find out the actual error. One interesting point is that if I debug the controller while running the Windows App, the patch method does not get called.
Ok, so I have finally solved this. Just a recap for those who could experience the same issue. I have an Odata WebApi controller, Windows 8 Store Application using WCF Client Library, with the reference created from Add Service Reference. When trying to update (patch) a record an exception was being thrown at the EndSaveChanges. This is because for some reason Post Tunneling is enabled by default on my context. Setting this to false allowed everything to work.
Context.UsePostTunneling = false;
Context.IgnoreResourceNotFoundException = true;

servicestack - caching a service response using redis

I have a servicestack service which when called via the browser (restful) Url ex:http://localhost:1616/myproducts, it works fine.
The service method has RedisCaching enabled. So first time it hits the data repository and caches it for subsequent use.
My problem is when I try calling it from a c# client via Soap12ServiceClient. It returns the below error:
Error in line 1 position 183. Expecting element '<target response>'
from namespace 'http://schemas.datacontract.org/2004/07/<target namespace>'..
Encountered 'Element' with name 'base64Binary',
namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.
Below is my Client code:
var endpointURI = "http://mydevelopmentapi.serverhostingservices.com:1616/";
using (IServiceClient client = new Soap12ServiceClient(endpointURI))
{
var request = new ProductRequest { Param1 = "xy23432"};
client.Send<ProductResponse>(request);
}
It seems that the soapwsdl used is giving the problem, but I appear to have used the defaults as generated by servicestack..
Any help will be much appreciated.
Update
I was able over come this error by changing the cache code at the service end:
Code that returned error at client end:
return RequestContext.ToOptimizedResultUsingCache(this.CacheClient, cacheKey,
() =>
new ProductResponse(){CreateDate = DateTime.UtcNow,
products = new productRepository().Getproducts(request)
});
Code that works now:
var result = this.CacheClient.Get<ProductResponse>(cacheKey);
if (result == null)
{
this.CacheClient.Set<ProductResponse>(cacheKey, productResult);
result = productResult;
}
return result;
But I am still curious to know why the first method (RequestContext.ToOptimizedResultUsingCache) returned error at c# client?
But I am still curious to know why the first method (RequestContext.ToOptimizedResultUsingCache) returned error at c# client?
From what I can tell, the ToOptimizedResultUsingCache is trying to pull a specific format (xml, html, json, etc) out of the cache based on the RequestContext's ResponseContentType (see code here and here). When using the Soap12ServiceClient the ResponseContentType is text/html (not sure if this is correct/intentional within ServiceStack). So what ToOptimizedResultUsingCache is pulling out of the cache is a string of html. The html string is being returned to the Soap12ServiceClient and causing an exception.
By pulling directly out of the cache you are bypassing ToOptimizedResultUsingCache's 'format check' and returning something the Soap12ServiceClient can handle.
** If you are using Redis and creating your key with UrnId.Create method you should see a key like urn:ProductResponse:{yourkey}.html
Thanks for your response paaschpa.
I revisited the code and I was able to fix it. Since your response gave me the direction, I have accepted your answer. Below is my fix.
I moved the return statement from RequestContext to the response DTO.
Code which throws error when used via c# client (code was returning entire requestcontext):
return RequestContext.ToOptimizedResultUsingCache(this.CacheClient, cacheKey,
() =>
new ProductResponse(){CreateDate = DateTime.UtcNow,
products = new productRepository().Getproducts(request)
});
Fixed Code (return moved to response DTO):
RequestContext.ToOptimizedResultUsingCache(this.CacheClient, cacheKey,
() => {
return new ProductResponse(){CreateDate = DateTime.UtcNow,
products = new productRepository().Getproducts(request)
}
});

Resources