我正在学习如何使用我的localhost上的Visual Studio 2012连接到ASP.NET Web API服务。
以下是示例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);
}
}
}
我正在尝试使用以下代码连接到此Web API:
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;
}
}
我在App.config中有以下内容(我在网上找到了这个):
<system.net>
<defaultProxy enabled="false" useDefaultCredentials="false">
<proxy/>
<bypasslist/>
<module/>
</defaultProxy>
</system.net>
执行此行时,应用程序停止执行:
HttpResponseMessage response = await client.GetAsync("api/products/1");
导致这种情况的原因是什么?
提前致谢
修改
这是错误:
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:
答案 0 :(得分:1)
我发现您正在使用Calling a Web API From a .NET Client in ASP.NET Web API 2 (C#)
中的控制台应用程序示例我需要做同样的事情,但在Windows应用程序中我通过做两件事来解决它。在我的Click事件中(并且使用对函数的调用应该是相同的)不要使用.Wait()。使用Async修饰符标记事件/函数,并使用await
调用async方法private async void btnSave_Click(object sender, EventArgs e)
{
await RunAsyncGet();
}
将RunAsync方法从static更改为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;
}
}
}
呼叫将在没有应用程序静止的情况下运行并完成。将RunAsync方法更改为private后,您将可以访问应用程序上的所有控件,并使用来自HTTPClient的响应,例如显示消息/或更新标签或网格等。
答案 1 :(得分:0)
有几个可能的问题。
我认为最可能的原因是在您的客户端代码中;我怀疑你进一步调用堆栈,你的代码正在调用从Wait
方法返回的任务Result
或async
。这将cause a deadlock,正如我在博客中描述的那样。解决方案是将Task.Wait
或Task<T>.Result
的所有来电替换为await
,并允许async
自然增长。
如果不是这样的话,还有另外一件事要检查(实际上,即使上面的段落解决了这个问题,检查这个也是个好主意)。在服务器端,确保ASP.NET应用程序的目标是.NET 4.5 和具有httpRuntime.targetFramework
set to 4.5
in its web.config
。