Tuesday, May 29, 2018

Web API CORS configuration : The requested resource does not support http method 'OPTIONS' error

After creating a web api project from VS 2015 template I was not able to authenticate (or access any other controller method) using ajax query.


After searching for some time I found out that config.EnableCors(); method call in WebApiConfig file can solve this problem.

However, this extension method is not available until Microsoft.AspNet.WebApi.Cors nuget package has been added to the project. The code is as show below:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("http://www.example.com", "*", "*");
        config.EnableCors(cors);

        // ...
    }
}
# Global.asax.cs
protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}
To call the api method from jquery client application use this format:
        var url = "https://localhost:44331/api/values";
     
 
        $.ajax({
            type: "GET",
            //headers: { "X-My-Custom-Header": "some value" },
            url: url
        }).done(function (data) {
            console.log(data);
        });
Copied from: https://stackoverflow.com/questions/27504256/mvc-web-api-no-access-control-allow-origin-header-is-present-on-the-requested




Thursday, May 24, 2018

Restrict website access based on IP address


IIS allows website access restrictions by adding configuration settings in web.config file

But the error pages are not easy to configure on a per site basis. Therefore, a custom action filter attribute which restricts access to our controllers based on request ip address is much desirable since it allows to redirect to a custom error page with a theme similar to the main site theme.

The following article explains an excellent implementation of this concept.

http://randyburden.com/blog/2011/08/09/restrict-access-to-an-mvc-action-or-controller-by-ip-address-using-a-custom-action-filter/

Copying code from the above article for the sake of my future reference


using System;
using System.Web;
using System.Web.Mvc;
using System.Configuration;
 
namespace YourMVCApplication.Filters
{
    /// <summary>
    /// Only allows authorized IP addresses access.
    /// </summary>
    public class AuthorizeIPAddressAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //Get users IP Address
            string ipAddress = HttpContext.Current.Request.UserHostAddress;
 
            if (!IsIpAddressValid(ipAddress.Trim()))
            {
                //Send back a HTTP Status code of 403 Forbidden 
                filterContext.Result = new HttpStatusCodeResult(403);
            }
 
            base.OnActionExecuting(filterContext);
        }
         
        /// <summary>
        /// Compares an IP address to list of valid IP addresses attempting to
        /// find a match
        /// </summary>
        /// <param name="ipAddress">String representation of a valid IP Address</param>
        /// <returns></returns>
        public static bool IsIpAddressValid(string ipAddress)
        {
            //Split the users IP address into it's 4 octets (Assumes IPv4)
            string[] incomingOctets = ipAddress.Trim().Split(new char[] { '.' });
 
            //Get the valid IP addresses from the web.config
            string addresses =
              Convert.ToString(ConfigurationManager.AppSettings["AuthorizeIPAddresses"]);
 
            //Store each valid IP address in a string array
            string[] validIpAddresses = addresses.Trim().Split(new char[] { ',' });
 
            //Iterate through each valid IP address
            foreach (var validIpAddress in validIpAddresses)
            {
                //Return true if valid IP address matches the users
                if (validIpAddress.Trim() == ipAddress)
                {
                    return true;
                }
 
                //Split the valid IP address into it's 4 octets
                string[] validOctets = validIpAddress.Trim().Split(new char[] { '.' });
 
                bool matches = true;
 
                //Iterate through each octet
                for (int index = 0; index < validOctets.Length; index++)
                {
                    //Skip if octet is an asterisk indicating an entire
                    //subnet range is valid
                    if (validOctets[index] != "*")
                    {
                        if (validOctets[index] != incomingOctets[index])
                        {
                            matches = false;
                            break; //Break out of loop
                        }
                    }
                }
 
                if (matches)
                {
                    return true;
                }
            }
 
            //Found no matches
            return false;
        }
    }
}

c# httpclient The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch

 If we get this error while trying to get http reponse using HttpClient object, it could mean that certificate validation fails for the remo...