从 c#(基于 win32)客户端调用 ASP.NET

Call ASP.NET from c# (win32 based) client

我有一个使用 ASP.NET 创建的 Web 应用程序和一个用 c# 编写的 windows 本机客户端程序。
windows 本机程序需要从 ASP.NET 网络应用程序发送和获取数据。
我想在 Web 应用程序中我需要一个用于外部调用的控制器。在客户端软件中,我需要以某种方式调用它们。

例如,我想将此 class 的实例传输到 ASP.NET 网络应用程序或从中传输:

public class Address
{
  public String Street {get;set;}
  public String City {get;set;}
}
public class CustomerInformation
{
 public String No {get;set;}
 public String Name {get;set;}
 public List<Address> Addresses {get;set;}
}

当然,Windows 客户端 运行 在本地某处,而 ASP.NET 服务 运行 在网络中。

我会添加 API 控制器并在其中放置一些方法。例如

// Addresses API 
public class AddressController : ApiController
{
    private readonly IRepository<Address> _repository;

    public AddressController(IRepository<Address> repository)
    {
        _repository = repository;
    }

    [BasicAuthorize]
    public IList<Address> GetList()
    {
        return _repository.GetAll();
    }
}

// Constomer information API
public class CustomerInformationController : ApiController
{
    private readonly IRepository<CustomerInformation> _repository;

    public CustomerInformationController(IRepository<CustomerInformation> repository)
    {
        _repository = repository;
    }

    [BasicAuthorize]
    public IList<CustomerInformation> GetList()
    {
        return _repository.GetAll();
    }
}

要保护这些方法,您可以使用基本身份验证。这意味着您可以为每个请求添加授权header:

例如,它如何查找密码为 "test"

的用户 "myuser"

授权:基本bXl1c2VyOnRlc3Q=

// Custom attribute for Basic authentication
public class BasicAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    private readonly string[] _permissionNames;

    public BasicAuthorizeAttribute()
    {
    }

    public BasicAuthorizeAttribute(params string[] permissionNames)
    {
        _permissionNames = permissionNames;
    }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        // check if user has been already authorized
        if (base.IsAuthorized(actionContext))
            return true;

        var user = AuthenticateUser(actionContext);

        // here you can check roles and permissions

        return user != null;
    }

    private IUser AuthenticateUser(HttpActionContext context)
    {
        var request = context.Request;
        AuthenticationHeaderValue authHeader = request.Headers.Authorization;
        if (authHeader != null)
        {
            // RFC 2617 sec 1.2, "scheme" name is case-insensitive
            if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) && authHeader.Parameter != null)
                return AuthenticateUser(authHeader.Parameter);
        }
        return null;
    }

    private IUser AuthenticateUser(string credentials)
    {
        try
        {
            // parse values
            var encoding = Encoding.GetEncoding("iso-8859-1");
            credentials = encoding.GetString(Convert.FromBase64String(credentials));

            var credentialsArray = credentials.Split(':');
            var username = credentialsArray[0];
            var password = credentialsArray[1];

            // authentication
            var membershipService = new IMembershipService();
            return membershipService.ValidateUser(username, password);
        }
        catch (Exception)
        {
            // Credentials were not formatted correctly.
            return null;
        }
    }
}

在客户端,您可以使用 HttpClient 发送异步请求

    public async Task<Address[]> GetAddresses() {
        var client = new HttpClient {BaseAddress = new Uri(_settingsService.GetHost())};
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var base64 = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "myuser", "test")));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",base64);

        HttpResponseMessage response = await client.GetAsync("api/addresses");
        if (response.StatusCode != HttpStatusCode.OK)
            throw new Exception(response.ReasonPhrase);

        string content = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<Address[]>(content);
    } 

Is there a way to achieve calls with complex data types (lists of classes) as parameters?

是的,作为ASP.NET或ASP.NETMVC或(最好)ASP.NETWEBAPI的服务器应用程序可以提供复杂数据类型的服务。事实上,声明方法没有限制。

How do I secure the calls from the client? Simple http-logon?

ASP.NET(MVC、WEB API)中有广泛的身份验证和授权机制,您可以选择其中之一。

您的客户端和服务器之间的数据传输通过 XML 或 JSON。

"WebClient" class 提供了从客户端到服务器进行调用所需的一切。

更多信息: