目标

简化并统一程序获取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 };
}
}

C#对WebApi数据操作的更多相关文章

  1. StackExchange.Redis帮助类解决方案RedisRepository封装(字符串类型数据操作)

    本文版权归博客园和作者本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/tag/NoSql/ 目录 一.基础配置封装 二.String字符串类型数据操作封 ...

  2. hive数据操作

    mdl是数据操作类的语言,包括向数据表加载文件,写查询结果等操作 hive有四种导入数据的方式 >从本地加载数据 LOAD DATA LOCAL INPATH './examples/files ...

  3. Dapper 数据操作框架

    数据操作DapperFrom NuGet:Install-Package DapperorInstall-Package Dapper.StrongName微型ORM:PetaPoco获得PetaPo ...

  4. Django数据操作F和Q、model多对多操作、Django中间件、信号、读数据库里的数据实现分页

    models.tb.objects.all().using('default'),根据using来指定在哪个库里查询,default是settings中配置的数据库的连接名称. 外话:django中引 ...

  5. coreData数据操作

    // 1. 建立模型文件// 2. 建立CoreDataStack// 3. 设置AppDelegate 接着 // // CoreDataStack.swift // CoreDataStackDe ...

  6. Entity Framework 5.0系列之数据操作

    Entity Framework将概念模型中定义的实体和关系映射到数据源,利用实体框架可以将数据源返回的数据具体化为对象:跟踪对象所做的更改:并发处理:将对象更改传播到数据源等.今天我们就一起讨论如何 ...

  7. 数据操作语言DML与运算符

    数据操作语言DML(添加,修改,删除) 1.添加数据 insert into insert into 表名 (字段列表) values (值列表),值列表要和字段列表按顺序匹配. insert int ...

  8. SQL不同服务器数据库之间的数据操作整理(完整版)

    ---------------------------------------------------------------------------------- -- Author : htl25 ...

  9. C#利用SqlDataAdapte对DataTable进行批量数据操作

    C#利用SqlDataAdapte对DataTable进行批量数据操作,可以让我们大大简化操作数据的代码量,我们几乎不需要循环和不关心用户到底是新增还是修改,更不用编写新增和修改以及删除的SQL语句, ...

随机推荐

  1. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

  2. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  3. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  4. 23种设计模式--工厂模式-Factory Pattern

    一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...

  5. C++中的命名空间

    一,命名空间(namespace)的基本概念以及由来 1.什么是标识符: 在C++中,标识符可以是基本的变量,类,对象,结构体,函数,枚举,宏等. 2.什么是命名空间: 所谓的命名空间是指标识符的可见 ...

  6. IE8/9 本地预览上传图片

    本地预览的意思是,在选择图片之后先不上传到服务器,而是由一个<img>标签来预览本地的图片,非 IE8/9 浏览器可以从<input type="file"/&g ...

  7. 28个你必须知道的HTML5的新特性,技巧以及技术

    崭新新的页面布局 传统的: HTML5: 1. 新的Doctype 尽管使用<!DOCTYPE html>,即使浏览器不懂这句话也会按照标准模式去渲染 2. Figure元素 用<f ...

  8. Node.js使用PM2的集群将变得更加容易

    介绍 众所周知,Node.js运行在Chrome的JavaScript运行时平台上,我们把该平台优雅地称之为V8引擎.不论是V8引擎,还是之后的Node.js,都是以单线程的方式运行的,因此,在多核心 ...

  9. iOS--->微信支付小结

    iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...

  10. 在jexus下如何简单的配置多站点

    参考:linuxdot.net 其实jexus的配置还是比较简单的,目录即站点(一个目录就是一个站点,一个配置文件就是一个站点) 如uustudy.net,在siteconf目录下创建一个uustud ...