1. 程式人生 > >.Net WebAPI 訪問其他項目層操作

.Net WebAPI 訪問其他項目層操作

color reat array ppa use {0} req mat otf

1.首先,配置一個公用的WEBAPI服務接口:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPIService.Utility;   ---引用的層
using Exceptions;                   ---引用的層

namespace Syngenta.FWA.WebUI.Controllers
{
    [RoutePrefix(
"api/AppService")] public class AppServiceController : ApiController { // GET api/<controller> public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/<controller>/5 public string Get(string
jsonParams) { return null; } //POST api/<controller> [Route("Post")] public IHttpActionResult Post([FromBody]JsonContainer container) { try { return Ok(container.GetObject()); }
catch (Exception Ex) { ExceptionManager.Publish(Ex); return BadRequest(dEx.Message); } catch (Exception ex) { var cutomException = GetCustomException(ex); ExceptionManager.Publish(cutomException); return BadRequest(cutomException.Message); } } [Route("PostActionList")] public IHttpActionResult PostActionList(JsonContainer[] containerList) { try { object[] objList = new object[containerList.Length]; for (int i = 0; i < containerList.Length; ++i) objList[i] = containerList[i].GetObject(); return Ok(objList); } catch (Exception ex) { ExceptionManager.Publish(ex); return BadRequest(ex.Message + "=>" + ex.StackTrace); } } [Route("PostService")] [HttpPost] public IHttpActionResult PostService([FromBody]JsonContainer container) { try { return Ok(container.GetObjectFromService()); } catch (Exception ex) { return BadRequest(ex.Message + "=>" + ex.StackTrace); } } [Route("PostAction")] [HttpPost] public IHttpActionResult PostAction([FromBody]JsonContainer container) { try { return Ok(container.GetObjectFromAction()); } catch (Exception ex) { return BadRequest(ex.Message + "=>" + ex.StackTrace); } } // PUT api/<controller>/5 public void Put(int id, [FromBody]string value) { } // DELETE api/<controller>/5 public void Delete(int id) { } private Exception GetCustomException(Exception exception) { if (exception.GetType() == typeof(Exception)) { return exception; } if (exception.InnerException != null) { return GetCustomException(exception.InnerException); } return exception; } } }

2.在引用的項目層裏添加JasonContainer類(即引用),用來訪問對應的類 ,規則是以BL開頭及以Service結尾的.cs文件,通過反射生產對應的類實例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace WebAPIService
{
    public class JsonContainer
    {
        const string BusinessNamespace = "BusinessLayer.";

        const string ServiceNamespace = "WebAPIService.Implements.";

        const string AdapterNamespace = "WebAPIService.Adapter.";

        public string Class { get; set; }

        public string Action { get; set; }

        public Dictionary<string, object> Parameters { get; set; }

        public object GetObject()
        {
            if (this.Class.EndsWith("service", StringComparison.OrdinalIgnoreCase))
            {
                var t = Type.GetType(ServiceNamespace + Class);
                if (t == null) t = Type.GetType(ServiceNamespace + "BL" + Class);
                object obj = Activator.CreateInstance(t);
                var method = FindMethod(t);
                return method.Invoke(obj, GetParameters(method));
            }
            else
            {
                if (!Class.StartsWith("BL", StringComparison.OrdinalIgnoreCase)) Class = "BL" + Class;

                Assembly assembly = AssemblyProvider.Provider.GetAssembly(AssemblyProvider.BusinessAssembly);
                var t = assembly.GetType(BusinessNamespace + Class);
                object bl = Activator.CreateInstance(t); //BL class instance
                var method = FindMethod(t);

                //Find if there‘s adpater
                var tAdapter = Assembly.GetCallingAssembly().GetType(AdapterNamespace + Class + "Adapter");

                if (tAdapter == null)
                {
                    return CallMethod(bl, method);
                }
                else
                {
                    object objAdapter = Activator.CreateInstance(tAdapter);
                    MethodInfo methodAdapter = tAdapter.GetMethod(Action + "Convert");
                    if (methodAdapter == null)  //No such Apdater method, invoke BL method directly
                        return CallMethod(bl, method);
                    return methodAdapter.Invoke(objAdapter, new object[] { Parameters, bl, method });
                }
            }
        }

        private MethodInfo FindMethod(Type t)
        {
            var members = t.GetMember(Action, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance);

            if (members.Length == 1) return members.Single() as MethodInfo;
            else if (members.Length > 1)
            {
                var methods = members.Cast<MethodInfo>().Where(m => m.GetParameters().Length == this.Parameters.Count);

                foreach (var m in methods)  //Find method with consistent parameter names
                {
                    var matched = m.GetParameters().Select(p => p.Name).SequenceEqual(this.Parameters.Keys);
                    if (matched) return m;
                }
            }

            throw new EntryPointNotFoundException(String.Format("{0} Not Found in {1}", Action, Class));
        }

        [Obsolete]
        public object GetObjectFromService()
        {
            Type t = Type.GetType(ServiceNamespace + Class);
            object obj = Activator.CreateInstance(t);
            MethodInfo method = t.GetMethod(Action);
            if (method.GetParameters().Length > 0)
                return method.Invoke(obj, new object[] { Parameters });
            else
                return method.Invoke(obj, null);
        }

        [Obsolete]
        public object GetObjectFromAction()
        {
            Assembly assembly = AssemblyProvider.Provider.GetAssembly(AssemblyProvider.BusinessAssembly);
            Type t = assembly.GetType(BusinessNamespace + Class);
            object obj = Activator.CreateInstance(t);
            MethodInfo method = t.GetMethod(Action);

            Type tAdapter = Type.GetType(AdapterNamespace + Class + "Adapter");
            object objAdapter = Activator.CreateInstance(tAdapter);
            MethodInfo methodAdapter = tAdapter.GetMethod(Action + "Convert");
            return methodAdapter.Invoke(objAdapter, new object[] { Parameters, obj, method });
        }

        private object CallMethod(object bl, MethodInfo method)
        {
            var pValues = GetParameters(method);
            return method.Invoke(bl, pValues);
        }

        /// <summary>
        /// Generete parameters order by the method‘s signature
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        private object[] GetParameters(MethodInfo method)
        {
            var pValues = method.GetParameters().Select(p =>
            {
                var value = this.Parameters.Single(p2 => p2.Key.Equals(p.Name, StringComparison.OrdinalIgnoreCase)).Value;
                return value == null || value.GetType() == p.ParameterType ? value : Convert.ChangeType(value, p.ParameterType);
            }).ToArray();

            if (pValues.Length == 0) return null;
            return pValues;
        }
    }
}

3.在引用的項目層裏添加AssemblyProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace WebAPIService
{
    public class AssemblyProvider
    {
        static readonly AssemblyProvider instance = new AssemblyProvider();

        public const string BusinessAssembly = "BusinessLayer";

        static readonly Assembly businessAssembly = Assembly.Load(BusinessAssembly);

        static AssemblyProvider()
        {
        }

        AssemblyProvider()
        {
        }

        public Assembly GetAssembly(string assembleName)
        {
            if (assembleName == BusinessAssembly)
                return businessAssembly;
            return null;
        }

        public static AssemblyProvider Provider
        {
            get
            {
                return instance;
            }
        }
    }
}

4.WebAPIConig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace Syngenta.FWA.WebUI
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

前臺代碼可以配置一個公用的訪問層來調用webapi (以AngularJS為例)

(function () {
    ‘use strict‘;

    angular
        .module(‘fwa‘)
        .factory(‘webapi‘, webapi);

    webapi.$inject = [‘$http‘, ‘$httpParamSerializer‘];

    function webapi($http, $httpParamSerializer) {

        return {

            post: function (className, actionName, parameters) {

                return $http({
                    method: ‘POST‘,
                    url: ‘api/AppService/Post‘,
                    data: JSON.stringify({ Class: className, Action: actionName, Parameters: parameters })
                });

            },

            getMenu: function () {
                return $http({
                    method: ‘get‘,
                    url: ‘api/Security‘
                });
            },

            postList: function (actionList) {
                return $http({
                    method: ‘POST‘,
                    url: ‘api/AppService/PostActionList‘,
                    data: JSON.stringify(actionList)
                });
            }

        }


    }


})();

.Net WebAPI 訪問其他項目層操作