创建模板_创建基于ABP模板项目的.NET WebApi项目

在ABP模板项目中,WebApi模块中通过dynamic webapi技术将所有实现了IApplicationService的类型自动创建对应的动态webapi,进而外部可以直接调用。但是这里的WebApi模块不是真正意义上的.NET WebApi项目,只是一个类库。本文章记录在ABP模板项目的基础上,创建.NET WebApi项目,并沿用ABP模板项目中的数据仓储方式和模块式开发。

一、创建.NET WebApi项目

  • 项目结构

a7e237ff4cb4834c515a73d4c7eeaef7.png
  • 基于OWIN的token认证

首先在App_Start下生成OWIN的Startup.cs类,并设置为Bearer token认证方式

Nuget安装

Microsoft.AspNet.WebApi.Owin
Microsoft.Owin.Security.OAuth
Microsoft.Owin.Cors

Startup.cs代码

using System.Web.Http;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Security.OAuth;
using Owin;

[assembly: OwinStartup(typeof(AbpDemo.TrueWebApi.App_Start.Startup))]

namespace AbpDemo.TrueWebApi.App_Start
{
    public class Startup
    {
        public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            ConfigureOAuth(app);

            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter("Bearer"));
            WebApiConfig.Register(config);
            app.UseCors(CorsOptions.AllowAll);
            app.UseWebApi(config);
        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
            app.UseOAuthBearerAuthentication(OAuthBearerOptions);
        }
    }
}

创建OauthController用于生成token

using AbpDemo.TrueWebApi.App_Start;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Security;
using System;
using System.Security.Claims;
using System.Web.Http;

namespace AbpDemo.TrueWebApi.Controllers
{
    public class OauthController : ApiController
    {
        [HttpPost]
        [Route("oauth/token")]
        public string Token(string account, string password)
        {
            var token = string.Empty;

            if (/* account validation success *)
            {
                var oAuthIdentity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
                oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, account));

                var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
                var currentUtc = new SystemClock().UtcNow;
                ticket.Properties.IssuedUtc = currentUtc;
                ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromDays(30));
                token = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
            }

            return token;
        }
    }
}

以上只是WebApi项目常规生成token的方式,既然项目依赖于ABP,因此有必要以module的形式创建项目怒,并沿用ABP模板项目中的登录方式。

二、Module式WebApi项目

项目中的Controller需要继承AbpApiController

Nuget安装

Abp
Abp.Web
Abp.Web.Api
Abp.Owin
Abp.Zero
EntityFramework
Microsoft.AspNet.WebApi.Cors
  • 创建AbpDemoTrueWebApiModule.cs

在App_Start下创建AbpDemoTrueWebApiModule.cs

using Abp.Configuration.Startup;
using Abp.Modules;
using Abp.WebApi;
using System.Reflection;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace AbpDemo.TrueWebApi.App_Start
{
    [DependsOn(typeof(AbpWebApiModule),
        typeof(AbpDemoApplicationModule),
        typeof(AbpDemoCoreModule),
        typeof(AbpDemoDataModule))]
    public class AbpDemoTrueWebApiModule : AbpModule
    {
        public override void Initialize()
        {
            base.Initialize();
            Configuration.Modules.AbpWeb().AntiForgery.IsEnabled = false;
        }

        public override void PreInitialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

            var cors = new EnableCorsAttribute("*", "*", "*");
            Configuration.Modules.AbpWebApi().HttpConfiguration.EnableCors(cors);
            Configuration.Modules.AbpWebApi().HttpConfiguration.SuppressDefaultHostAuthentication();
            Configuration.Modules.AbpWebApi().HttpConfiguration.Filters.Add(new HostAuthenticationFilter("Bearer"));

            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}
  • 修改Global.asax.cs
using Abp.Web;
using AbpDemo.TrueWebApi.App_Start;
using System;

namespace AbpDemo.TrueWebApi
{
    public class WebApiApplication : AbpWebApplication<AbpDemoTrueWebApiModule>
    {
        protected override void Application_Start(object sender, EventArgs e)
        {
            base.Application_Start(sender, e);
        }
    }
}
  • 修改OauthController

这里照搬AbpDemo.WebApi/AccountController

LoginModel.cs

using System.ComponentModel.DataAnnotations;

namespace AbpDemo.Api.Models
{
    public class LoginModel
    {
        public string TenancyName { get; set; }

        [Required]
        public string UsernameOrEmailAddress { get; set; }

        [Required]
        public string Password { get; set; }
    }
}

OauthController.cs

using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.UI;
using Abp.WebApi.Controllers;
using AbpDemo.Authorization;
using AbpDemo.Authorization.Users;
using AbpDemo.MultiTenancy;
using AbpDemo.TrueWebApi.Models;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System;
using System.Threading.Tasks;
using System.Web.Http;

namespace AbpDemo.TrueWebApi.Controllers
{
    public class OauthController : AbpApiController
    {
        public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

        private readonly LogInManager _logInManager;

        static OauthController()
        {
            OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        }

        public OauthController(LogInManager logInManager)
        {
            _logInManager = logInManager;
        }

        [HttpPost]
        [Route("oauth/token")]
        public async Task<OAuthResult> OAuth(LoginModel loginModel)
        {
            var oauthResult = new OAuthResult();
            try
            {
                var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);

                var ticket = new AuthenticationTicket(loginResult.Identity, new AuthenticationProperties());

                var currentUtc = new SystemClock().UtcNow;
                ticket.Properties.IssuedUtc = currentUtc;
                ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
                string token = OAuthBearerOptions.AccessTokenFormat.Protect(ticket);

                oauthResult.Code = 0;
                oauthResult.Message = "Success";
                oauthResult.Data = new TokenOutput { Token = token };
            }
            catch (Exception ex)
            {
                oauthResult.Code = 1;
                oauthResult.Message = ex.Message;
            }

            return oauthResult;
        }

        private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName)
        {
            var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);

            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    return loginResult;
                default:
                    throw CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName);
            }
        }

        private Exception CreateExceptionForFailedLoginAttempt(AbpLoginResultType result, string usernameOrEmailAddress, string tenancyName)
        {
            switch (result)
            {
                case AbpLoginResultType.Success:
                    return new ApplicationException("Don't call this method with a success result!");
                case AbpLoginResultType.InvalidUserNameOrEmailAddress:
                case AbpLoginResultType.InvalidPassword:
                    return new UserFriendlyException("LoginFailed", "InvalidUserNameOrPassword");
                case AbpLoginResultType.UserIsNotActive:
                    return new UserFriendlyException("LoginFailed", "UserIsNotActiveAndCanNotLogin");
                case AbpLoginResultType.UserEmailIsNotConfirmed:
                    return new UserFriendlyException("LoginFailed", "Your email address is not confirmed. You can not login"); //TODO: localize message
                default: //Can not fall to default actually. But other result types can be added in the future and we may forget to handle it
                    return new UserFriendlyException("LoginFailed");
            }
        }
    }

    public class OAuthResult
    {
        public int Code { get; set; }

        public string Message { get; set; }

        public TokenOutput Data { get; set; }
    }

    public class TokenOutput
    {
        public string Token { get; set; }
    }
}
  • 修改Startup.cs
using Abp.Owin;
using AbpDemo.TrueWebApi.Controllers;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(AbpDemo.TrueWebApi.App_Start.Startup))]

namespace AbpDemo.TrueWebApi.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseAbp();
            app.UseOAuthBearerAuthentication(OauthController.OAuthBearerOptions);
        }
    }
}

至此,获取token的代码已经完成,现在使用ABP模板项目的默认账号密码:admin/123qwe 进行测试(记得在web.config添加数据库连接字符串),测试结果如下图:

a4ba3a9a259c6f05cb1e52d1c957297f.png

三、Application层访问测试

现在已经可以得到token,那么可以利用这个token直接调用Application层的IApplicationService方法从而获取数据呢?

在AbpDemo.Core中创建Client Entity,并在AbpDemo.Application创建ClientAppService并进行登录认证和权限检查

using Abp.Application.Services;
using Abp.Application.Services.Dto;
using AbpDemo.Clients.Dto;

namespace AbpDemo.Clients
{
    public interface IClientAppService : IAsyncCrudAppService<ClientDto, int, PagedResultRequestDto, CreateClientDto, UpdateClientDto>
    {
    }
}
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using AbpDemo.Authorization;
using AbpDemo.Clients.Dto;

namespace AbpDemo.Clients
{
    [AbpAuthorize(PermissionNames.Pages_Users)]
    public class ClientAppService : AsyncCrudAppService<Client, ClientDto, int, PagedResultRequestDto, CreateClientDto, UpdateClientDto>, IClientAppService
    {
        public ClientAppService(IRepository<Client, int> repository) : base(repository)
        {
        }
    }
}

在ResultController中通过构造函数注入的方式将IClientAppService注入进来,然后直接进行方法调用

using Abp.Application.Services.Dto;
using Abp.Domain.Uow;
using Abp.Web.Models;
using Abp.WebApi.Authorization;
using Abp.WebApi.Controllers;
using AbpDemo.Clients;
using System.Threading.Tasks;
using System.Web.Http;

namespace AbpDemo.TrueWebApi.Controllers
{
    [AbpApiAuthorize]
    public class ResultController : AbpApiController
    {
        private readonly IClientAppService _clientAppService;

        public ResultController(IClientAppService clientAppService)
        {
            _clientAppService = clientAppService;
        }

        [HttpGet]
        [UnitOfWork(false, IsDisabled = true)]
        public async Task<AjaxResponse> GetClientById(int id)
        {
            var client = await _clientAppService.Get(new EntityDto<int>(id));
            return new AjaxResponse(client);
        }
    }
}

测试结果如下图:

054560dc1606e1109af71af9466c255a.png

大功告成!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值