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 };
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM