WebAPI

//1.restful 是一种架构风格,接口的设计风格
//  一切都是资源,
//  所有资源有统一的接口四种接口:Create--Post,Read--Get,Update--Put/Patch,Delete--Delete
//  基于http,无状态
//2.URI 统一资源标志符,资源的唯一标识;URL 统一资源定位符,资源的地址;URL是URI的子集
//3.RPC(Remote Procedure Call)RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果

//4.网站启动执行Application_Start()-->给Route增加地址规则-->请求进来时会经过路由匹配合适的控制器-->根据HttpMethod找方法(根据方法名开头匹配)
//  方法名以Get开头或者有特性[HttpGet],就是get请求
//5.特性路由,学习博客https://www.cnblogs.com/lgx5/p/10967720.html
//  config.MapHttpAttributeRoutes();注册路由时加上这个方法就是启用特性路由
//  [Route("api/values/{id}/V2")]方法上加上自定义路由
//  路由可以增加约束 [Route("api/values/{id:int}/V2")],可空 [Route("api/values/{id:int?}/V2")],默认值 [Route("api/values/{id=10}/V2")]

//6.配合IOC
//  a.实现下IDependencyResolver,构造函数传入IUnityContainer
//    在GetService和GetServices方法中根据传入的类型构造对象
//  b.网站初始化方法中config.DependencyResolver = new UnityDependencyResolver(ContainerFactory.Container);
//    把默认的DependencyResolver换成自己的Resolver,传入Container
//7.权限认证
//  默认不支持Session,可以自行扩展支持(不推荐)
//  1)登录成功,服务器生成token/ticket,账号+密码+时间+其他信息(ip等),返回token/ticket
//  2)请求时,带上token/ticket
//  3)服务器验证token/ticket
//  4)每个方法都验证token/ticket,可以用filter来实现
//8.异常处理Filter
//  自己定义的特性要继承ExceptionFilterAttribute,覆写OnException方法处理异常
//  发现抓不到HttpResponseException这类异常,可以抓到Exception
//  作用域只是方法内部
//9.全局异常处理
//  自己定义异常处理类继承ExceptionHandler,覆写ShouldHandle和Handle
//  替换框架自带的异常处理类config.Services.Replace(typeof(IExceptionHandler), new CustomExceptionHandler());
//  和IOC的初始化冲突了
//10.ActionFilter  方法执行前后可以加动作
//  自定义特性,继承ActionFilterAttribute,覆写OnActionExecuting和OnActionExecuted
//11.跨域 浏览器的同源策略限制
//  但是浏览器自己的行为不受影响,js/css/img/iframe等的地址
//  解决方法:Jsonp和Cors
//  Jsonp 用script标签的src请求回来js代码执行,试下跨域
//  Cors: 返回头加上Access-Control-Allow-Origin,它的值是允许跨域的域名
//        有个包using System.Web.Http.Cors;可以在不同作用域实现
//12.WebAPI 寄宿
//  必须引用System.Web.dll,除此外还引用其他
//  引用必须的dll:System.Web.Http.SelfHost.dll;System.Web.Http.dll;System.Net.Formatting.Http.dll;System.Net.Http.dll
//  可以安装包Microsoft.AspNet.WebApi和Microsoft.AspNet.WebApi.SelfHost 就把除System.Web.dll外所有dll自动引用
//13.自动生成WebAPI文档  \Areas\HelpPage\Views\Help\DisplayTemplates\index.cshtml
//  http://localhost:8087/help/index#endregion

 

using MySOA.WebAPI.Utinity;
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;
using Unity;

namespace MySOA.WebAPI
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);//WebAPI注册,MVC是没有这个的
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

        #region 开启session
        public override void Init()
        {
            this.AuthorizeRequest += GlobalAuthorizeRequest;
            base.Init();
        }

        private void GlobalAuthorizeRequest(object sender, EventArgs e)
        {
            //启用WebApi中的session
            HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
        }
        #endregion
    }
}

初始化基本都在这

using MySOA.WebAPI.Utinity;
using MySOA.WebAPI.Utinity.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Http.ExceptionHandling;

namespace MySOA.WebAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务

            //全局异常处理:用自定义的代替框架原本的
            config.Services.Replace(typeof(IExceptionHandler), new CustomExceptionHandler());

            //用自己的DependencyResolver替换框架默认的,在自己写的中传入UnityContainer
            //实现IOC
            config.DependencyResolver = new UnityDependencyResolver(ContainerFactory.Container);

            特性初始化时添加,对全局生效
            //config.Filters.Add(new CustomBasicAuthorazeAttribute());

            允许全局跨域
            //config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

            // Web API 路由
            config.MapHttpAttributeRoutes();

            //自己定义路由
            config.Routes.MapHttpRoute(
                name: "CustomerApi",//默认路由
                routeTemplate: "api/{controller}/{action}/{id}",//api开头,第二个是控制器,第三个是参数
                defaults: new { id = RouteParameter.Optional }
            );

            config.Routes.MapHttpRoute(
                name: "DefaultApi",//默认路由
                routeTemplate: "api/{controller}/{id}",//api开头,第二个是控制器,第三个是参数
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

特性路由

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MySOA.WebAPI.Controllers
{
    //加上这个特性,所有的特性路由就能省略这一节
    //如果不想用,根节点前加~,[Route("~api/values/{id:int}/V2")]
    //[RoutePrefix("api/Values")]  
    public class ValuesController : ApiController
    {
        //部署IIS时遇到无权访问配置文件和无权访问站点的情况,添加了两个用户IIS_IUSERS,IUSR

        // GET api/values
        [HttpGet]
        public IEnumerable<string> LGet()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        [Route("api/values/{id:int}/V2")]//特性路由,并且路由加上了int类型的约束
        public string GetV2(int id)
        {
            return "valueV2";
        }

        [Route("api/values/{name}/V2")]//特性路由
        public string GetV2(string name)
        {
            return $"value {name}";
        }

        [Route("api/values/V2/{id}/{name}")]//父类下的资源,两个参数
        public string GetV2(string id, string name)
        {
            return $"value {id}_{name}";
        }

        // POST api/values
        public void Post([FromBody] string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody] string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }
}

IOC实现

using Microsoft.Practices.Unity.Configuration;
using MySOA.WebAPI.Interface;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
using Unity;

namespace MySOA.WebAPI.Utinity
{
    public class ContainerFactory
    {
        public static IUnityContainer Container { get; }

        static ContainerFactory()
        {
            #region 读配置固定写法,不用关心
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();//
            fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"CfgFiles\Unity.config");
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
            #endregion
            //声明容器
            Container = new UnityContainer();
            //这个是配置中容器的名字<container>标签
            configSection.Configure(Container, "WebAPIContainer");
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using Unity;

namespace MySOA.WebAPI.Utinity
{
    //控制器实例化
    public class UnityDependencyResolver : IDependencyResolver
    {
        private IUnityContainer UnityContainer = null;

        public UnityDependencyResolver(IUnityContainer unityContainer)
        {
            this.UnityContainer = unityContainer;
        }

        public IDependencyScope BeginScope()//作用域
        {
            return new UnityDependencyResolver(this.UnityContainer.CreateChildContainer());
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposedManage)
        {
            if (disposedManage)
            {
                this.UnityContainer.Dispose();
            }
        }

        ~UnityDependencyResolver()
        {
            //必须是false
            this.Dispose(false);
        }
        //下面这两个方法用来构造对象
        public object GetService(Type serviceType)
        {
            try
            {
                return this.UnityContainer.Resolve(serviceType);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                //这样写是可以的,因为在WebApi中除了会构造我们的对象外还会构造一些框架的对象,会异常,返回null没关系
                return null;
            }

        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return this.UnityContainer.ResolveAll(serviceType);
            }
            catch (Exception ex)
            {
                return new List<object>();
                Console.WriteLine(ex.ToString());
                return null;
            }
        }
    }
}

Form认证

[CustomAllowAnonymous]
[HttpGet]
public string Login(string account, string password)
{
	if ("admin".Equals(account) && "123456".Equals(password))
	{
		FormsAuthenticationTicket ticketObj = new FormsAuthenticationTicket(0, account, DateTime.Now, DateTime.Now.AddHours(1),
			true, $"{account}&{password}", FormsAuthentication.FormsCookiePath);
		var rst = new { Result = true, Ticket = FormsAuthentication.Encrypt(ticketObj) };
		return JsonConvert.SerializeObject(rst);
	}
	else
	{
		return JsonConvert.SerializeObject(new { Result = false });
	}
}
$("#bntLoginSSO").on("click", function () {
                $.ajax({
                    url: "/api/users/SSOLoginTest",
                    type: "Get",
                    data: { "Account": $("#txtAccount").val(), "Password": $("#txtPassword").val() },
                    success: function (data) {
                        var rst = JSON.parse(data);
                        if (rst.Result) {
                            ticket = rst.Ticket;
                            alert(ticket);
                        }
                        else {
                            alert("fail");
                        }
                    },
                    dataType: "Json"
                });
            });
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Security;

namespace MySOA.WebAPI.Utinity.Filters
{
    public class CustomBasicAuthorazeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            //方法或者控制器上标记该特性就不验证了
            if (actionContext.ActionDescriptor.GetCustomAttributes<CustomAllowAnonymousAttribute>().FirstOrDefault() != null
                || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<CustomAllowAnonymousAttribute>().FirstOrDefault() != null)
            {
                return;
            }

            var authorization = actionContext.Request.Headers.Authorization;
            if (authorization != null && this.ValidateTicket(authorization.Parameter))
            {
                return;//有权限直接返回
            }
            else
            {
                //throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);
                this.HandleUnauthorizedRequest(actionContext);
            }
        }

        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            var challengeMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized);//告诉浏览器要验证
            challengeMessage.Headers.Add("Www-Authenticate", "Basic");//权限信息放在basic
            //actionContext.Request.CreateResponse().Headers.Add("Www-Authenticate", "Basic");
            actionContext.Response = challengeMessage;
            base.HandleUnauthorizedRequest(actionContext);
        }

        private bool ValidateTicket(string encryptTicket)
        {
            if (string.IsNullOrEmpty(encryptTicket))
                return false;
            //Ticket解密
            var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;
            //验证账号密码
            return string.Equals(strTicket, "admin&123456");
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MySOA.WebAPI.Utinity.Filters
{
    public class CustomAllowAnonymousAttribute : Attribute
    {
    }
}

 

异常处理Filter

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http.Filters;

namespace MySOA.WebAPI.Utinity.Filters
{
    public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            Console.WriteLine(actionExecutedContext.Exception.Message);//记录日志
            actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(
                System.Net.HttpStatusCode.OK,
                new
                {
                    Result = true,
                    Message = "发生异常"
                });//创造一个返回
        }
    }
}

全局异常处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http.ExceptionHandling;
using System.Web.Http.Results;

namespace MySOA.WebAPI.Utinity.Filters
{
    /// <summary>
    /// 全局异常处理
    /// 发现和Unity的IOC冲突了,注释自己定义的UnityDependencyResolver后起作用
    /// </summary>
    public class CustomExceptionHandler : ExceptionHandler
    {
        /// <summary>
        /// 自己确定哪些情况的异常要处理--自己写规则
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        //public override bool ShouldHandle(ExceptionHandlerContext context)
        //{
        //    string url = context.Request.RequestUri.AbsoluteUri;
        //    return url.Contains("/api");
        //}

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="context"></param>
        public override void Handle(ExceptionHandlerContext context)
        {
            检查Exception类型,异常的详细信息
            //if (context.Exception is HttpException)
            //{ 
            
            //}

            context.Result = new ResponseMessageResult(context.Request.CreateResponse(
                System.Net.HttpStatusCode.OK,
                new
                {
                    Result = false,
                    Message = "发生异常",
                    Bug = context.Exception.Message
                }));
        }
    }
}

ActionFilter

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace MySOA.WebAPI.Utinity.Filters
{
    public class CustomActionFilterAttribute: ActionFilterAttribute
    {
        /// <summary>
        /// 执行前
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            Console.WriteLine("执行前");
        }

        /// <summary>
        /// 执行后
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            Console.WriteLine("执行后");
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:8087");
        }
    }
}

寄宿

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.SelfHost;

namespace MySOA.WebAPI.SelfBoarding
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var config = new HttpSelfHostConfiguration("http://localhost:7077");
                config.Routes.MapHttpRoute(name: "DefaultApi",//默认路由
                routeTemplate: "api/{controller}/{id}",//api开头,第二个是控制器,第三个是参数
                defaults: new { id = RouteParameter.Optional });
                using (var server = new HttpSelfHostServer(config))
                {
                    server.OpenAsync().Wait();
                    Console.WriteLine("服务已经启动");
                    Console.WriteLine("输入任意字符关闭");
                    Console.ReadKey();
                    server.CloseAsync().Wait();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MySOA.WebAPI.SelfBoarding
{
    //加上这个特性,所有的特性路由就能省略这一节
    //如果不想用,根节点前加~,[Route("~api/values/{id:int}/V2")]
    //[RoutePrefix("api/Values")]  
    public class TestController : ApiController
    {
        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值