Sample code for ASP. NET MVC API interface validation

  • 2021-10-15 10:21:19
  • OfStack

There is a message interface in the project, which receives messages and displays messages from other systems. Referring to some API verification methods on the Internet, it is found that the verification method provided by the general authority management system is the most perfect.

The complete idea sharing that will be implemented below

1. WebApiConfig Global Processing


/// <summary>
  /// WebApiConfig 
  ///  Routing base configuration. 
  /// 
  /// 
  ///  Modify record 
  /// 
  ///    2016.11.01  Version: 2.0  Song Biao   Unify the date format 1 Handle. 
  ///    2016.10.30  Version: 2.0  Song Biao   Solve json Circular reference problem during serialization. 
  ///    2016.10.28  Version: 2.0  Song Biao   Return response format  $format  Support. 
  ///    2016.09.01  Version: 1.0  Song Biao    Create. 
  /// 
  ///  Version: 1.0
  /// 
  /// <author>
  ///    <name> Song Biao </name>
  ///    <date>2016.09.01</date>
  /// </author> 
  /// </summary>
  public static class WebApiConfig
  {
    /// <summary>
    ///  Register the Global Configuration Service 
    /// </summary>
    /// <param name="config"></param>
    public static void Register(HttpConfiguration config)
    {
      // Web API configuration and services

      // Mandatory https Visit 
      //config.Filters.Add(new ForceHttpsAttribute());
      //  Unified 1 Return format 
      config.Filters.Add(new ApiResultAttribute());
      //  Handling when an exception occurs 
      config.Filters.Add(new ApiErrorHandleAttribute());
      // ToKen Authentication filter   More convenient   You don't need to be here anymore   Those with changed labels will be automatically checked 
      //config.Filters.Add(new ApiAuthFilterAttribute());
      //  Solve json Circular reference problem during serialization 
      config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
      // Unify the date format 1 Deal with 
      config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
      new IsoDateTimeConverter()
      {
        DateTimeFormat = "yyyy-MM-dd hh:mm:ss"
      }
      );

      // Web API routes  Route 
      config.MapHttpAttributeRoutes();

      config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
      );

      //  Kill XML Serializer 
      //config.Formatters.Remove(config.Formatters.XmlFormatter);
      // In the requested Url Plus  ?$format=xml You can specify the response format 
      config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
      config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
    }
  }

2. Authentication Filter


  using DotNet.Business;
  using DotNet.Utilities;
  using DotNet.Tracking.API.Common;

  /// <summary>
  /// ApiAuthFilterAttribute
  ///  Authentication filter , Have ApiAuthFilterAttribute Label properties are automatically checked by the method 
  /// 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-11  Version: 1.0 SongBiao  Create a file.   
  /// 
  /// <author>
  ///   <name>SongBiao</name>
  ///   <date>2016-10-11</date>
  /// </author>
  /// </summary>
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
  public class ApiAuthFilterAttribute : AuthorizationFilterAttribute
  {
    /// <summary>
    ///  Prompt information when not authorized 
    /// </summary>
    private const string UnauthorizedMessage = " Request unauthorized, access denied. ";

    /// <summary>
    ///  Permission access 
    /// </summary>
    /// <param name="actionContext"></param>
    public override void OnAuthorization(HttpActionContext actionContext)
    {
      base.OnAuthorization(actionContext);
      //  Allow anonymous access 
      if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0) 
      {
        return;
      }

      string systemCode = APIOperateContext.Current.SystemCode;
      string permissionCode = APIOperateContext.Current.PermissionCode;
      string appKey = APIOperateContext.Current.AppKey;
      string appSecret = APIOperateContext.Current.AppSecret;      
      if (string.IsNullOrWhiteSpace(appKey) || string.IsNullOrWhiteSpace(appSecret))
      {
        // Unauthenticated (logged in) users ,  And non-anonymous access, go to the login page  
        //actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        //actionContext.Response.Content = new StringContent("<p>Unauthorized</p>", Encoding.UTF8, "text/html");
        var response = actionContext.Response= actionContext.Response?? new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.Unauthorized;
        BaseResult result = new BaseResult
        {
          Status = false,
          StatusMessage = UnauthorizedMessage
        };
        response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
      }
      else
      {
        //  Check  AppKey  And  AppSecret
        BaseResult result = BaseServicesLicenseManager.CheckService(appKey, appSecret, false, 0, 0, systemCode, permissionCode);
        if (!result.Status)
        {
          var response = actionContext.Response = actionContext.Response?? new HttpResponseMessage();
          response.Content = new StringContent(result.ToJson(), Encoding.UTF8, "application/json");
        }
      }
           
    }
  }

3. Unified 1 return format


  /// <summary>
  /// ApiResultAttribute
  ///  Unified 1 Return format 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-31  Version: 1.0  Song Biao   Create a file. 
  /// 
  /// <author>
  ///   <name> Song Biao </name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class ApiResultAttribute : ActionFilterAttribute
  {
    /// <summary>
    ///  Processing of rewrite return 
    /// </summary>
    /// <param name="actionExecutedContext"></param>
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
      //  The express tracking interface transmits format You don't have to go here 
      if (actionExecutedContext.Request.Properties.ContainsKey("format"))
      {
        //  If an exception occurs, it will not be handled here   Handling in exceptions  ApiErrorHandleAttribute
        if (actionExecutedContext.Exception != null)
          return;
        base.OnActionExecuted(actionExecutedContext);
        var result = new ApiResultModel();
        //  Obtain by  API  Status code returned 
        result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
        //  Obtain by  API  Data returned 
        result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
        //  Recapsulate the backhaul format 
        actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
      }
    }
  }

4. Global exception handling


  using DotNet.Utilities;
  using DotNet.Tracking.API.Common;
  using DotNet.Tracking.API.Controllers;
  using DotNet.Tracking.API.Models;

  /// <summary>
  /// ApiErrorHandleAttribute
  ///  Global exception handling 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-31  Version: 1.0  Song Biao   Create a file. 
  /// 
  /// <author>
  ///   <name> Song Biao </name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>

  public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
  {
    /// <summary>
    ///  Anomaly series 1 Deal with 
    /// </summary>
    /// <param name="actionExecutedContext"></param>
    public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
    {
      base.OnException(actionExecutedContext);
      //  Get the error message when an exception occurs 
      var errorMessage = actionExecutedContext.Exception.Message;

      //  Exception record 
      string parameters = APIOperateContext.GetRequestParameters();
      NLogHelper.Trace(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException  Complete request address and parameters   :  " + parameters);
      // 2016-11-01  Add an exception mail reminder 
      NLogHelper.InfoMail(actionExecutedContext.Exception, BaseSystemInfo.SystemCode + " ApiErrorHandleAttribute OnException  Complete request address and parameters   :  " + parameters);

      var result = new ApiResultModel()
      {
        Status = HttpStatusCode.BadRequest,
        ErrorMessage = errorMessage
      };
      //  Repackage the returned message 
      actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
    }
  }

5. Context of interface operation


  using DotNet.Business;
  using DotNet.Model;
  using DotNet.Utilities;

  /// <summary>
  /// APIOperateContext
  ///  Context of interface operation 
  ///  Context-sensitive 1 Some general-purpose things are disposed of here 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-31  Version: 1.0  Song Biao   Create a file. 
  /// 
  /// <author>
  ///   <name> Song Biao </name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class APIOperateContext
  {
    /// <summary>
    ///  Gets the current   Operation context  ( For each server thread that processes browser requests   Create separately   Operation context )
    /// </summary>
    public static APIOperateContext Current
    {
      get
      {
        APIOperateContext oContext = CallContext.GetData(typeof(APIOperateContext).Name) as APIOperateContext;
        if (oContext == null)
        {
          oContext = new APIOperateContext();
          CallContext.SetData(typeof(APIOperateContext).Name, oContext);
        }
        return oContext;
      }
    }

    #region Http Context   And   Related attributes 
    /// <summary>
    /// Http Context 
    /// </summary>
    public HttpContext ContextHttp
    {
      get
      {
        return HttpContext.Current;
      }
    }

    /// <summary>
    ///  Output object 
    /// </summary>
    public HttpResponse Response
    {
      get
      {
        return ContextHttp.Response;
      }
    }

    /// <summary>
    ///  Request object 
    /// </summary>
    public HttpRequest Request
    {
      get
      {
        return ContextHttp.Request;
      }
    }

    /// <summary>
    /// Session Object 
    /// </summary>
    System.Web.SessionState.HttpSessionState Session
    {
      get
      {
        return ContextHttp.Session;
      }
    }
    #endregion

    /// <summary>
    ///  Gets all request parameters, get And post Adj.   Simplified version 
    /// </summary>
    public static string GetRequestParameters()
    {
      string query = HttpContext.Current.Request.Url.Query;
      NameValueCollection nvc;
      string baseUrl;
      ParseUrl(query, out baseUrl, out nvc);
      List<string> list = new List<string>() { };
      foreach (var key in nvc.AllKeys)
      {
        list.Add(key + "=" + nvc[key]);
      }

      var form = HttpContext.Current.Request.Form;
      foreach (var key in form.AllKeys)
      {
        list.Add(key + "=" + form[key]);
      }
      string result = HttpContext.Current.Request.Url.AbsoluteUri + "?" + string.Join("&", list);

      return result;
    }

    /// <summary>
    ///  Analysis  url  Parameter information in string 
    ///  Aim at get Requested 
    /// </summary>
    /// <param name="url"> Input  URL</param>
    /// <param name="baseUrl"> Output  URL  The basic part of </param>
    /// <param name="nvc"> Output obtained after analysis  ( Parameter name , Parameter value )  Collection of </param>
    public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
    {
      if (url == null)
      {
        throw new ArgumentNullException("url");
      }
      nvc = new NameValueCollection();
      baseUrl = "";
      if (url == "")
      {
        return;
      }
      int questionMarkIndex = url.IndexOf('?');
      if (questionMarkIndex == -1)
      {
        baseUrl = url;
        return;
      }
      baseUrl = url.Substring(0, questionMarkIndex);
      if (questionMarkIndex == url.Length - 1)
      {
        return;
      }
      string ps = url.Substring(questionMarkIndex + 1);
      //  Start analyzing parameter pairs  
      Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
      MatchCollection mc = re.Matches(ps);
      foreach (Match m in mc)
      {
        nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
      }
    }

    /// <summary>
    ///  System number 
    /// </summary>
    public string SystemCode
    {
      get
      {
        return Request["systemCode"] ?? "Base";
      }
    }

    /// <summary>
    ///  Authority number 
    /// </summary>
    public string PermissionCode
    {
      get
      {
        return Request["permissionCode"];
      }
    }

    /// <summary>
    ///  The application of the access interface is transmitted AppKey
    /// </summary>
    public string AppKey
    {
      get
      {
        return Request["appKey"];
      }
    }

    /// <summary>
    ///  The application of the access interface is transmitted AppSecret
    /// </summary>
    public string AppSecret
    {
      get
      {
        return Request["appSecret"];
      }
    }

    private BaseUserInfo _userInfo = null;
    /// <summary>
    ///  Get the current user 
    ///  Through the interface AppKey And AppSecret Obtained user 
    /// </summary>
    /// <returns></returns>
    public BaseUserInfo UserInfo
    {
      get
      {
        BaseUserInfo userInfo = null;
        BaseUserEntity userEntity = BaseUserManager.GetObjectByCodeByCache(AppKey);
        if (userEntity != null)
        {
          if (BaseServicesLicenseManager.CheckServiceByCache(userEntity.Id, AppSecret))
          {
            userInfo = new BaseUserInfo();
            userInfo.Id = userEntity.Id;
            userInfo.RealName = userEntity.RealName;
            userInfo.UserName = userEntity.UserName;
            userInfo.IPAddress = Utilities.GetIPAddress(true);
          }
        }
        return userInfo;
      }
    }

    #region  Business library connection 
    /// <summary>
    ///  Business library connection 
    /// </summary>
    public static IDbHelper BusinessDbHelper
    {
      get
      {
        return DbHelperFactory.GetHelper(BaseSystemInfo.BusinessDbType, BaseSystemInfo.BusinessDbConnection);
      }
    }
    #endregion

    #region  User Center Library Connection 
    /// <summary>
    ///  User Center Library Connection 
    /// </summary>
    public static IDbHelper UserCenterDbHelper
    {
      get
      {
        return DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection);
      }
    }
    #endregion


  }

7. Unified 1 Return Format Entity


  /// <summary>
  /// ApiResultModel
  ///  Unified 1 Return format entity 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-31  Version: 1.0  Song Biao   Create a file. 
  /// 
  /// <author>
  ///   <name> Song Biao </name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  public class ApiResultModel
  {
    public HttpStatusCode Status { get; set; }

    //public JsonResult<T> Data { get; set; }
    public object Data { get; set; }
    public string ErrorMessage { get; set; }
  }

8. Message related interface


  /// <summary>
  /// MessageBookController
  ///  Message related interface 
  /// 
  ///  Record modification 
  /// 
  /// 2016-10-31  Version: 1.0  Song Biao   Create a file. 
  /// 
  /// <author>
  ///   <name> Song Biao </name>
  ///   <date>2016-10-31</date>
  /// </author>
  /// </summary>
  [ApiAuthFilter]
  public class CustomerMessageController : ApiController
  {
    /// <summary>
    ///  Save the message information of the order number 
    /// </summary>
    /// <param name="messageBook"></param>
    /// <returns></returns>
    [HttpPost]
    //[AllowAnonymous]  Add this label if you don't need verification 
    public IHttpActionResult Add([FromBody]MsgbookCusEntity messageBook)
    {
      BaseResult baseResult = new BaseResult();
      if (string.IsNullOrWhiteSpace(messageBook.SystemFrom))
      {
        baseResult.Status = false;
        baseResult.StatusMessage = "SystemFrom Parameter cannot be null ";
      }
      else
      {
        try
        {
          MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
          MsgbookCusEntity model = new MsgbookCusEntity();
          model.Id = Guid.NewGuid().ToString("N");
          model.Message = messageBook.Message;
          model.SendEmail = messageBook.SendEmail;
          model.SendTelephone = messageBook.SendTelephone;
          model.Message = messageBook.Message;
          model.BillCode = messageBook.BillCode;
          model.SystemFrom = messageBook.SystemFrom;
          model.DeletionStateCode = 0;
          manager.Add(model, false, false);

          baseResult.Status = true;
          baseResult.StatusMessage = " Added successfully. ";
        }
        catch (Exception ex)
        {
          NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage  Anomaly ");
          baseResult.Status = false;
          baseResult.StatusMessage = " Exception: " + ex.Message;
        }
      }

      return Ok(baseResult);
    }

    /// <summary>
    ///  Get a message with a single number 
    /// </summary>
    /// <param name="billCode"></param>
    /// <returns></returns>
    [HttpGet]
    public IHttpActionResult GetList(string billCode)
    {
      JsonResult<List<MsgbookCusEntity>> jsonResult = new JsonResult<List<MsgbookCusEntity>>();
      try
      {
        MsgbookCusManager manager = new MsgbookCusManager(APIOperateContext.BusinessDbHelper, APIOperateContext.Current.UserInfo);
        List<MsgbookCusEntity> list = new List<MsgbookCusEntity>();
        list = manager.GetList<MsgbookCusEntity>(new KeyValuePair<string, object>(MsgbookCusEntity.FieldBillCode, billCode)
        , new KeyValuePair<string, object>(MsgbookCusEntity.FieldDeletionStateCode, 0));

        jsonResult.Status = true;
        jsonResult.RecordCount = list.Count;
        jsonResult.Data = list;
        jsonResult.StatusMessage = " Achieve success ";
      }
      catch (Exception ex)
      {
        NLogHelper.Warn(ex, "CustomerMessageController AddBillMessage  Anomaly ");
        jsonResult.Status = false;
        jsonResult.StatusMessage = " Exception: " + ex.Message;
      }

      return Ok(jsonResult);
    }
  }

9. Interface call method


    /// <summary>
    ///  Test message interface call 
    /// </summary>
    /// <returns></returns>
    public ActionResult AddCustomerMessage()
    {
      string url = "http://192.168.1.88:808/api/CustomerMessage/Add?";
      WebClient webClient = new WebClient();
      NameValueCollection postValues = new NameValueCollection();

      postValues.Add("Message", " Fill in your message ");
      postValues.Add("SendEmail", "youemail@qq.com");
      postValues.Add("SendTelephone", "021-60375335");
      postValues.Add("Code", "661137858");
      postValues.Add("AppKey", "wssavbcn");
      postValues.Add("AppSecret", "350e66b1e6564b0a817163erwwwwe8");
      postValues.Add("SystemFrom", " Official website ");

      byte[] responseArray = webClient.UploadValues(url, postValues);
      string response = Encoding.UTF8.GetString(responseArray);

      return Content(response);
    }

Related articles: