• 《.NET开发之BS+CS混合模式下的应用开发思路》


    背景

    目前公司开发的程序为C/S模式(客户端+服务器)的方式开发,但是在实际的应用过程中需要开放一些web服务去给三方使用,比如:和微信公众号对接。
    对接需要按WebApi的形式去提供给外部系统,这样就会导致需要基于业务数据重新开发WebApi的服务,并将原有的C/S业务方法开放接口,供WebApi调用。
    那么如果我们是从无到有开发新项目的时候,是否需要改善一下设计的模式来达到:不管是C/S还是B/S都能够同时获取到业务数据。

    设计思路

    项目大致采用以下结构:
    【SJ.WebApi】.Net MVC WebAPI-可部署Swagger UI提供给外部系统调用的WebApi接口

    【SJ.Model】类库-实体

    【SJ.IBLL】类库-接口层

    【SJ.BLL】类库-业务层

    【SJ.UI】WinForm-客户端UI层

     数据请求示例

    开发实例

    用户表:

    SELECT * FROM dbo.[User]
    

    按规范创建接口类:
    【SJ.IBLL】接口层--》IUserService.cs

    使用面向接口开发的原则,业务调用时统一通过用户接口:IUserService去调用业务方法

    namespace SJ.IBLL
    {
        public interface IUserService
        {
            /// <summary>
            /// 用户登录
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            BaseModel<bool> CheckLogin(User user);
    
            /// <summary>
            /// 查询所有用户
            /// </summary>
            /// <returns></returns>
            List<User> QueryAllUser();
    
            /// <summary>
            /// 添加用户信息
            /// </summary>
            /// <returns></returns>
            BaseModel<bool> AddUser(User user);
        }
    }
    

    【SJ.BLL】业务层--》UserService.cs

    namespace SJ.BLL.Service
    {
        public class UserService: IUserService
        {
            SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = "Data Source=localhost;Initial Catalog=CS_BS_WEBAPI_TEST;User Id=sa;Password=123!@#;",
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true
            });
    
            /// <summary>
            /// 用户登录
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            public BaseModel<bool> CheckLogin(User user)
            {
                BaseModel<bool> result = new BaseModel<bool>();
                result.Rt = true;
                result.Rd = "登录成功";
                result.Rn = 1;
                var users = db.Queryable<User>().Where(o => o.UserName == user.UserName && o.PassWord == user.PassWord).ToList();
                if (users.Count == 0)
                {
                    result.Rt = false;
                    result.Rd = "账号或密码错误";
                    result.Rn = -1;
                }
                return result;
            }
    
            /// <summary>
            /// 查询所有用户
            /// </summary>
            /// <returns></returns>
            public List<User> QueryAllUser()
            {
                var users = db.Queryable<User>().ToList();
                return users;
            }
    
            /// <summary>
            /// 添加用户信息
            /// </summary>
            /// <returns></returns>
            public BaseModel<bool> AddUser(User user)
            {
                BaseModel<bool> result = new BaseModel<bool>();
                result.Rt = true;
                result.Rd = "用户注册成功";
                result.Rn = 1;
                int tl = db.Insertable(user).ExecuteCommand();
                if (tl <= 0)
                {
                    result.Rt = false;
                    result.Rd = "用户注册失败";
                    result.Rn = -1;
                }
                return result;
            }
        }
    }
    

    因为不管是C/S客户端还是B/S控制器做数据请求前必须先new IUserService()实例化接口,此时因为接口的特性不允许被实例化。
    我们需要创建一个工厂类,为业务调用时生成对应的业务接口。
    【SJ.IBLL】接口层--》IUserFactory.cs
    使用反射的原理创建接口的子类:

    namespace SJ.IBLL
    {
        public class IUserFactory
        {
            public static IUserService CreateUserService()
            {
                Type type = typeof(IUserService);
                IUserService service = (IUserService)Activator.CreateInstance(System.Type.GetType("SJ.BLL.Service.UserService,SJ.BLL"), null);
                return service;
            }
        }
    }
    

    客户端调用业务:

    /// <summary>
    /// 创建接口
    /// </summary>
    IUserService iserver = IUserFactory.CreateUserService();
    //请求数据
    var result = iserver.CheckLogin(user);
    

    WebApi接口调用业务:

    /// <summary>
    /// 创建接口
    /// </summary>
    IUserService iserver = IUserFactory.CreateUserService();
    
    
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    [HttpPost]
    public BaseModel<bool> CheckLogin(User user)
    {
        return iserver.CheckLogin(user);
    }
    

    遇到的坑

    1.net Core 5.0 WebApi发布到IIS报错

     访问报错:

    HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效。

    解决方案:

    1.给发布文件夹增加Everyone的所有权限

     2.安装对应版本的windows-hosting-bundle-installer

    下载地址:https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-aspnetcore-5.0.17-windows-hosting-bundle-installer

    在完成1、2两个步骤之后,访问IIS下的webapi站点,还是报错404

    3.修改web.config文件,追加以下内容

    <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>

     

     4.开发过程中添加控制器方法后访问报错

    将控制器默认的路由设置[Route("[controller]")],修改为[Route("api/[controller]/[action]")],重新启动项目成功。

     

    项目源码

    https://gitee.com/soulsjie/DoNet_BS_CS_WBAPI.git

  • 相关阅读:
    泛型约束where条件的使用(可以通过类型参数动态反射创建实例)
    设计模式之java源码-工厂方法模式
    软件定义网络基础---OF-Config协议
    软件定义网络基础---OpenFlow协议
    软件定义网络基础---南向接口协议概述
    软件定义网络基础---OpenFlow流表
    软件定义网络基础---OpenFlow概述
    软件定义网络基础---SDN数据平面
    软件定义网络基础---SDN的核心思想
    MACVLAN虚拟网卡技术
  • 原文地址:https://www.cnblogs.com/soulsjie/p/16419031.html
Copyright © 2020-2023  润新知