• 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 };
        }
    }
    
  • 相关阅读:
    HTML3 / 4 / 4.1 / 5 版本升级过程中,变化是怎么样的
    HTML head内所有标签,及其作用
    HTML 和 XHTML和区别
    HTML DOCTYPE 都有哪些,它们之前的区别和用途分别是什么?
    eclipse中英文切换--四种方式
    Eclipse Class Decompiler---Java反编译插件
    jdk历史版本下载
    eclipse优化(部分)
    博客迁移到github
    JavaScript:同步、异步和事件循环
  • 原文地址:https://www.cnblogs.com/zhang740/p/3865394.html
Copyright © 2020-2023  润新知