C#对WebApi数据操作

目标

简化并统一程序获取WebApi对应实体数据的过程,方便对实体进行扩充。原理就是数据服务使用反射发现数据提供者,处理好泛型就行。

相关传送门:Restful WebApi开发实践

先来看下最后的请求效果:(插件服务总线用的是服务定位器设计模式)

private IModelDataService MDS = BundleServiceBus.Current.GetInstance<IModelDataService>();

//获取对应实体数据
MDS.GetDataByModel<EntityModel, Guid>(new DataParameter
{
    TenantId = XXX,
    AggregationId = XXX,
    SiteId = XXX,
    CMD = "?xxx=xxx",
});

//带Id获取
MDS.GetDataByModel<EntityModel, Guid>(new DataParameter<Guid>
{
    TenantId = XXX,
    AggregationId = XXX,
    SiteId = XXX,
    DataId = XXX,
    CMD = "?xxx=xxx",
});

实现

通讯基础

HTTP通讯简单封装:(服务端使用了SSO、OAuth做授权)

public class DataWithOAuth : IDataWithOAuthService, IBundleServiceProvider
{
    public string LoginUserName { get; private set; }
    public string AccessToken { get; private set; }
    Uri BaseAddress { get; set; }

    public DataWithOAuth()
    {
        LoginUserName = "[未登录]";
    }

    private HttpClient GetHttpClient()
    {
        var client = new HttpClient
        {
            BaseAddress = BaseAddress
        };
        client.SetBearerToken(AccessToken);
        return client;
    }
    private OAuth2Client GetOAuth2Client()
    {
        return new OAuth2Client(
            new Uri("[oauthUrl]"),
            "[oauthClient]",
            "[oauthSecret]");
    }
    private AccessTokenResponse RequestToken(string username, string password, string scope)
    {
        var client = GetOAuth2Client();
        try
        {
            return client.RequestAccessTokenUserName(username, password, scope);
        }
        catch (Exception)
        {
            return null;
        }
    }

    public bool SetBaseUrl(string baseUrl)
    {
        if (!string.IsNullOrWhiteSpace(baseUrl)) BaseAddress = new Uri(baseUrl);
        return true;
    }

    public bool Login(string userName, string passWord)
    {
        var token = RequestToken(userName, passWord, "read");
        if (token != null)
        {
            LoginUserName = userName;
            AccessToken = token.AccessToken;
            return true;
        }
        return false;
    }

    #region 服务
    public ReturnHTTPData Get(string url)
    {
        try
        {
            var hc = GetHttpClient();
            var response = hc.GetAsync(url).Result;
            return new ReturnHTTPData
            {
                StatusCode = response.StatusCode.ToString(),
                ReasonPhrase = response.ReasonPhrase,
                Version = response.Version.ToString(),
                Content = response.Content.ReadAsStringAsync().Result
            };
        }
        catch (Exception ex)
        {
            return new ReturnHTTPData { Content = "Err:" + ex.Message };
        }
    }
    public ReturnHTTPData Post<T>(string url, T Data)
    {
        try
        {

            var hc = GetHttpClient();
            var response = hc.PostAsJsonAsync(url, Data).Result;
            return new ReturnHTTPData
            {
                StatusCode = response.StatusCode.ToString(),
                ReasonPhrase = response.ReasonPhrase,
                Version = response.Version.ToString(),
                Content = response.Content.ReadAsStringAsync().Result
            };
        }
        catch (Exception ex)
        {
            return new ReturnHTTPData { Content = "Err:" + ex.Message };
        }
    }
    public ReturnHTTPData Put<T>(string url, T Data)
    {
        try
        {
            var hc = GetHttpClient();
            var response = hc.PutAsJsonAsync(url, Data).Result;
            return new ReturnHTTPData
            {
                StatusCode = response.StatusCode.ToString(),
                ReasonPhrase = response.ReasonPhrase,
                Version = response.Version.ToString(),
                Content = response.Content.ReadAsStringAsync().Result
            };
        }
        catch (Exception ex)
        {
            return new ReturnHTTPData { Content = "Err:" + ex.Message };
        }
    }
    public ReturnHTTPData Delete(string url)
    {
        try
        {
            var hc = GetHttpClient();
            var response = hc.DeleteAsync(url).Result;
            return new ReturnHTTPData
            {
                StatusCode = response.StatusCode.ToString(),
                ReasonPhrase = response.ReasonPhrase,
                Version = response.Version.ToString(),
                Content = response.Content.ReadAsStringAsync().Result
            };
        }
        catch (Exception ex)
        {
            return new ReturnHTTPData { Content = "Err:" + ex.Message };
        }
    }
    #endregion
}

由于HTTP通讯这个服务我需要插件间调用,返回的数据模型我放到了契约项目内,为了不引用其他类库,所以根据需要对HttpResponseMessage的几个属性做了提取:

public class ReturnHTTPData
{
    public string Content { get; set; }
    public string StatusCode { get; set; }
    public string ReasonPhrase { get; set; }
    public string Version { get; set; }

    public string ErrorMessage { get { return StatusCode + ":" + ReasonPhrase + " " + Content; } }
}

数据参数模型

定义数据参数的模型:

public class DataParameter
{
    public Guid TenantId { get; set; }
    public Guid AggregationId { get; set; }
    public Guid SiteId { get; set; }
    public string CMD { get; set; }

    public static DataParameter Empty = new DataParameter();
}

public class DataParameter<IdType> : DataParameter
{
    public IdType DataId { get; set; }

    public new static DataParameter<IdType> Empty = new DataParameter<IdType>();
}

数据服务

定义一个数据服务接口:

public interface IModelDataService
{
    ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter dataParam);
    ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam);
    ReturnModelData<DataModelType> PostDataByModel<DataModelType, IdType>(DataParameter dataParam, DataModelType data);
    ReturnModelData<DataModelType> PutDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam, DataModelType data);
    ReturnModelData<DataModelType> DeleteDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam);
}

返回的数据类型:

public class ReturnModelData<DataModelType> : ReturnHTTPData
{
    public bool IsSuccess { get; set; }
    public List<DataModelType> Data { get; set; }
    public string Message { get; set; }
}

实现一个数据服务:

public class ModelDataService : IModelDataService, IBundleServiceProvider
{
    private Dictionary<Type, object> _data = new Dictionary<Type, object>();

    public ModelDataService()
    {
        var data = Assembly.GetExecutingAssembly().DefinedTypes.Where(s => s.BaseType == typeof(DataHelperBase));
        foreach (var typeInfo in data)
        {
            var ife = typeInfo.GetInterfaces();
            var dataHelper = Activator.CreateInstance(typeInfo);
            try
            {
                _data.Add(ife.First().GenericTypeArguments[0], dataHelper);
            }
            catch (Exception)
            {
            }
        }
    }

    public ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter dataParam)
    {
        object obj;
        if (_data.TryGetValue(typeof(DataModelType), out obj))
        {
            var dataProvider = obj as IDataProvider<DataModelType, IdType>;
            if (dataProvider != null) return dataProvider.GetData(dataParam);
        }
        return new ReturnModelData<DataModelType>
        {
            IsSuccess = false,
            Message = "未找到[" + typeof(DataModelType) + "]的数据提供者"
        };
    }

    public ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam)
    {
        object obj;
        if (_data.TryGetValue(typeof(DataModelType), out obj))
        {
            var dataProvider = obj as IDataProvider<DataModelType, IdType>;
            if (dataProvider != null) return dataProvider.GetData(dataParam);
        }
        return new ReturnModelData<DataModelType>
        {
            IsSuccess = false,
            Message = "未找到[" + typeof(DataModelType) + "]的数据提供者"
        };
    }

    public ReturnModelData<DataModelType> PostDataByModel<DataModelType, IdType>(DataParameter dataParam, DataModelType data)
    {
        object obj;
        if (_data.TryGetValue(typeof(DataModelType), out obj))
        {
            var dataProvider = obj as IDataProvider<DataModelType, IdType>;
            if (dataProvider != null) return dataProvider.PostData(dataParam, data);
        }
        return new ReturnModelData<DataModelType>
        {
            IsSuccess = false,
            Message = "未找到[" + typeof(DataModelType) + "]的数据提供者"
        };
    }

    public ReturnModelData<DataModelType> PutDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam, DataModelType data)
    {
        object obj;
        if (_data.TryGetValue(typeof(DataModelType), out obj))
        {
            var dataProvider = obj as IDataProvider<DataModelType, IdType>;
            if (dataProvider != null) return dataProvider.PutData(dataParam, data);
        }
        return new ReturnModelData<DataModelType>
        {
            IsSuccess = false,
            Message = "未找到[" + typeof(DataModelType) + "]的数据提供者"
        };
    }

    public ReturnModelData<DataModelType> DeleteDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam)
    {
        object obj;
        if (_data.TryGetValue(typeof(DataModelType), out obj))
        {
            var dataProvider = obj as IDataProvider<DataModelType, IdType>;
            if (dataProvider != null) return dataProvider.DeleteData(dataParam);
        }
        return new ReturnModelData<DataModelType>
        {
            IsSuccess = false,
            Message = "未找到[" + typeof(DataModelType) + "]的数据提供者"
        };
    }
}

数据提供者

定义一个数据提供者接口:

interface IDataProvider<DataModelType, IdType>
{
    ReturnModelData<DataModelType> GetData(DataParameter dataParam);
    ReturnModelData<DataModelType> GetData(DataParameter<IdType> dataParam);
    ReturnModelData<DataModelType> PostData(DataParameter dataParam, DataModelType data);
    ReturnModelData<DataModelType> PutData(DataParameter<IdType> dataParam, DataModelType data);
    ReturnModelData<DataModelType> DeleteData(DataParameter<IdType> dataParam);
}

定义数据提供者的基础属性:

abstract class DataProviderBase
{
    private IDataWithOAuthService _dwos;

    protected IDataWithOAuthService DWOS
    {
        get
        {
            if (_dwos == null)
            {
                _dwos = UppBundleEngine.Constants.BundleService.BundleServiceBus.Current
                    .GetInstance<IDataWithOAuthService>();
            }
            return _dwos;
        }
    }
}

剩下的就是体力活了,实现数据提供者,比如:

class MemberCardModelProvider : DataProviderBase, IDataProvider<MemberCardModel, string>
{
    public ReturnModelData<MemberCardModel> GetData(DataParameter dataParam)
    {
        var result = DWOS.Get("api/XXX/MemberCard/"
            + dataParam.TenantId + "/" + dataParam.AggregationId + "/" + dataParam.SiteId + dataParam.CMD);
        if (result.StatusCode == "OK")
        {
            var model = FastData.GetDataFromJson<MemberCardModel>(result.Content);
            return new ReturnModelData<MemberCardModel> { IsSuccess = true, Data = model };
        }
        return new ReturnModelData<MemberCardModel> { IsSuccess = false, Message = result.ErrorMessage };
    }

    public ReturnModelData<MemberCardModel> GetData(DataParameter<string> dataParam)
    {
        var result = DWOS.Get("api/XXX/MemberCard/"
            + dataParam.TenantId + "/" + dataParam.AggregationId + "/" + dataParam.SiteId + "/" + dataParam.DataId + dataParam.CMD);
        if (result.StatusCode == "OK")
        {
            var model = FastData.GetSingleDataFromJson<MemberCardModel>(result.Content);
            return new ReturnModelData<MemberCardModel> { IsSuccess = true, Data = new List<MemberCardModel> { model } };
        }
        return new ReturnModelData<MemberCardModel> { IsSuccess = false, Message = result.ErrorMessage };
    }

    public ReturnModelData<MemberCardModel> PostData(DataParameter dataParam, MemberCardModel data)
    {
        var result = DWOS.Post("api/XXX/MemberCard/"
            + dataParam.TenantId + "/" + dataParam.AggregationId + "/" + dataParam.SiteId + dataParam.CMD, data);
        if (result.StatusCode == "OK")
        {
            var model = FastData.GetSingleDataFromJson<MemberCardModel>(result.Content);
            return new ReturnModelData<MemberCardModel> { IsSuccess = true, Data = new List<MemberCardModel> { model } };
        }
        return new ReturnModelData<MemberCardModel> { IsSuccess = false, Message = result.ErrorMessage };
    }

    public ReturnModelData<MemberCardModel> PutData(DataParameter<string> dataParam, MemberCardModel data)
    {
        var result = DWOS.Put("api/XXX/MemberCard/"
            + dataParam.TenantId + "/" + dataParam.AggregationId + "/" + dataParam.SiteId + "/" + dataParam.DataId + dataParam.CMD, data);
        if (result.StatusCode == "NoContent")
        {
            return new ReturnModelData<MemberCardModel> { IsSuccess = true };
        }
        return new ReturnModelData<MemberCardModel> { IsSuccess = false, Message = result.ErrorMessage };
    }

    public ReturnModelData<MemberCardModel> DeleteData(DataParameter<string> dataParam)
    {
        var result = DWOS.Delete("api/XXX/MemberCard/"
            + dataParam.TenantId + "/" + dataParam.AggregationId + "/" + dataParam.SiteId + "/" + dataParam.DataId + dataParam.CMD);
        if (result.StatusCode == "OK")
        {
            var model = FastData.GetSingleDataFromJson<MemberCardModel>(result.Content);
            return new ReturnModelData<MemberCardModel> { IsSuccess = true, Data = new List<MemberCardModel> { model } };
        }
        return new ReturnModelData<MemberCardModel> { IsSuccess = false, Message = result.ErrorMessage };
    }
}
原文地址:https://www.cnblogs.com/zhang740/p/3865394.html