I am learning how to connect to a ASP.NET Web API service using Visual Studio 2012 on my localhost.
Here is the sample Web API Controller:
namespace ProductStore.Controllers
{
public class ProductsController : ApiController
{
static readonly IProductRepository repository = new ProductRepository();
public IEnumerable<Product> GetAllProducts()
{
return repository.GetAll();
}
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
public IEnumerable<Product> GetProductsByCategory(string category)
{
return repository.GetAll().Where(
p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
}
public HttpResponseMessage PostProduct(Product item)
{
item = repository.Add(item);
var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);
string uri = Url.Link("DefaultApi", new { id = item.Id });
response.Headers.Location = new Uri(uri);
return response;
}
public void PutProduct(int id, Product product)
{
product.Id = id;
if (!repository.Update(product))
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
public void DeleteProduct(int id)
{
repository.Remove(id);
}
}
}
I am trying to connect to this Web API with the following code:
static async Task RunAsyncGet()
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("/api/product/1");
if (response.IsSuccessStatusCode)
{
Product product = await response.Content.ReadAsAsync<Product>();
Console.WriteLine("{0}\t${1}\t{2}", product.Name, product.Price, product.Category);
}
}
}
catch (Exception ex)
{
throw;
}
}
I have the following in the App.config (I found this online):
<system.net>
<defaultProxy enabled="false" useDefaultCredentials="false">
<proxy/>
<bypasslist/>
<module/>
</defaultProxy>
</system.net>
When this line is executed, the application stops executing:
HttpResponseMessage response = await client.GetAsync("api/products/1");
What would be causing this?
Thanks in advance
EDIT
Here is the error:
System.Net.Http.HttpRequestException was caught HResult=-2146233088 Message=An error occurred while sending the request. Source=mscorlib StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ProductStoreClientFormsApplication.Form1.<RunAsyncGet>d__0.MoveNext() in h:\Learning\WEB API\ProductStoreClientFormsApplication\ProductStoreClientFormsApplication\Form1.cs:line 33 InnerException: System.Net.WebException
HResult=-2146233079
Message=The underlying connection was closed: Unable to connect to the remote server.
Source=System
StackTrace:
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
InnerException: System.Net.Sockets.SocketException
HResult=-2147467259
Message=An invalid argument was supplied
Source=System
ErrorCode=10022
NativeErrorCode=10022
StackTrace:
at System.Net.Sockets.Socket..ctor(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6)
at System.Net.PooledStream.Activate(Object owningObject, Boolean async, GeneralAsyncDelegate asyncCallback)
at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
InnerException:
I see that you are using the console application sample from Calling a Web API From a .NET Client in ASP.NET Web API 2 (C#)
I needed to do the same thing , but in a windows application and I solved it by doing 2 things. In my Click Event ( and should be the same using a call to a function ) do not use .Wait(). Mark the event/function with the Async modifier and call the async method using await
private async void btnSave_Click(object sender, EventArgs e)
{
await RunAsyncGet();
}
Change the RunAsync method from static to private .
private async Task RunAsyncGet()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56286/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("/api/product/1");
if (response.IsSuccessStatusCode)
{
Product product= await response.Content.ReadAsAsync<Product>();
SomeLabel.Text = product.Username;
}
}
}
The call will run and complete without the application coming to a stand still. After changing the RunAsync method to private you will have access to all the controls on the application and you use the response from the HTTPClient for example showing a message / or updating a label or Grid etc.
There are a couple of possible problems.
I believe the most likely cause is in your client code; I suspect that further up you call stack, your code is calling Wait
or Result
on the task returned from an async
method. This will cause a deadlock , as I describe on my blog. The solution is to replace all calls to Task.Wait
or Task<T>.Result
with await
and allow async
to grow naturally.
If that isn't the case, there is one other thing to check (actually, it's a good idea to check this even if the paragraph above solves the problem). On the server side, ensure that your ASP.NET app is targeting .NET 4.5 and has httpRuntime.targetFramework
set to 4.5
in its web.config
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.