Xamarin 和 IIS LocalHost WebApi 给出错误 - System.Net.Http.HttpRequestException:“网络子系统已关闭”

Bee*_*ees 7 c# xamarin asp.net-web-api2

我这里有 2 个应用程序。一个是 Xamarin 应用程序,另一个是 Asp.Net MVC 应用程序,它具有连接到 SqlServer 数据库的 WebApi,“其中数据库位于某个 IP 地址 xxx.xxx.xxx.xxx 之类的托管网站上”。

我在 IIS 本地运行 MVC 应用程序,然后在 IIS 中启动网站后,我从 Visual Studio 的第二个实例运行 Xamarin 应用程序。

首先,我认为 MVC WebApi 不会被调用,因为我尝试将断点放在那里,但它没有出现在那里。我不知道为什么。因为我对 Winforms 和 MVC 应用程序 (WebApi) 做了同样的事情,所以至少 WebApi 被调用了,我在 MVC 应用程序中看到了断点。

现在在 Xamarin 中,我收到此错误

System.Net.Http.HttpRequestException: 'Network subsystem is down'
Run Code Online (Sandbox Code Playgroud)

在行中

var responseTask = await client.GetAsync("ConnectToAscDatabase");
Run Code Online (Sandbox Code Playgroud)

我在 Xamarin 应用程序的 MainPage.cs 中有此代码

        private async void Button_OnClicked(object sender, EventArgs e)
        {
            HttpClientHandler handler = new HttpClientHandler();
            handler.UseDefaultCredentials = true;
            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = new Uri("http://localhost:49252/api/");

                // !!! This Line gives the error System.Net.Http.HttpRequestException: 'Network subsystem is down'
                var responseTask = await client.GetAsync("ConnectToAscDatabase");

                var readTask = responseTask.Content.ReadAsAsync<Microsoft.Data.SqlClient.SqlConnection>();
                SqlConnection con = readTask.Result;
                var staty = con.State;
            }
        }
Run Code Online (Sandbox Code Playgroud)

这是一个 WebApi

        public class ConnectToAscDatabaseController : ApiController
        {
            public async Task<Microsoft.Data.SqlClient.SqlConnection> Get()
            {
                string SqlServer_ServerPath_Server = "SomeServer";
                string SqlServer_Database_Server = "SomeDatabase";
                string SqlServer_User_Server = "SomeUser";
                string SqlServer_Password_Server = "SomePassword";
                int timeOutInSeconds = 15;
                string connectionString = "data source=" + SqlServer_ServerPath_Server + ";" + "initial catalog=" + SqlServer_Database_Server + ";" + "user id=" + SqlServer_User_Server + ";" + "Password=" + SqlServer_Password_Server + ";" + "Trusted_Connection=false" + ";" + "Connection Timeout=" + timeOutInSeconds + ";" + "Persist Security Info=False";
                SqlConnection con = new SqlConnection(connectionString);
                con.Open();
                return con;
            }
        }
Run Code Online (Sandbox Code Playgroud)

小智 9

根据本文档,Android 的网络地址空间负责,因为除了 IP 地址“10.0.2.2”之外,模拟器与本地计算机没有直接连接。您可以附加端口号来定位您想要访问的任何服务。

还值得注意的是,对于使用自签名证书运行的服务,由于信任问题,您仍然可能无法获得连接,因为 Android 和 IOS 不会尊重与使用自签名证书运行的服务的连接。从这里阅读更多内容

我使用以下代码来解决这些问题(在 Android 上):

共享项目(添加如下接口):

using System.Net.Http;

namespace DemoApp.Services
{
    public interface IHttpClientHandlerService
    {
        HttpClientHandler GetInsecureHandler();
    }
}
Run Code Online (Sandbox Code Playgroud)

Android项目(添加以下类):

using DemoApp.Droid.Services;
using DemoApp.Services;
using System.Net.Http;
using Xamarin.Forms;

[assembly: Dependency(typeof(HttpClientHandlerService))]
namespace DemoApp.Droid.Services
{
    public class HttpClientHandlerService : IHttpClientHandlerService
    {
        public HttpClientHandler GetInsecureHandler()
        {
            HttpClientHandler handler = new HttpClientHandler
            {
                ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
                {
                    if (cert.Issuer.Equals("CN=localhost"))
                        return true;
                    return errors == System.Net.Security.SslPolicyErrors.None;
                }
            };
            return handler;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在代码中使用以下命令创建一个新的 HttpClient:

#if DEBUG
    HttpClientHandler insecureHandler = DependencyService.Get<IHttpClientHandlerService>().GetInsecureHandler();
    HttpClient client = new HttpClient(insecureHandler);
#else
    HttpClient client = new HttpClient();
#endif
Run Code Online (Sandbox Code Playgroud)

注意:有更好的方法来创建 HttpClient(例如使用依赖项注入和 IHttpClientFactory),读者可以选择最适合他们的方法。

对于HttpClient的BaseAddress,也可以使用以下代码:

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
Run Code Online (Sandbox Code Playgroud)

其中端口 5000 可能是访问您的服务的端口,todoitems 可能是要调用的 api url。


Che*_*SFT -6

根据你的描述,你想在Xamarin.Forms中使用web api显示数据,有很多关于这方面的文章,你可以看一下:

https://www.c-sharpcorner.com/article/how-to-fetch-data-from-web-api-using-xamarin-forms/

您需要确保 Web API 项目已启动并正在运行,因为 Xamarin 应用程序将调用 WebAPI 来访问数据。

有关使用实体框架构建 ASP.NET Web API 以及从 SQL 服务器检索数据的更多详细信息,您还可以查看:

https://medium.com/better-programming/building-a-restful-api-with-asp-net-web-api-and-sql-server-ce7873d5b331