Varun Setia
Varun Setia

Reputation: 165

How to prevent partial view direct access from url in asp.net mvc core?

I want my partial view in asp.net mvc core to be only available through AJAX request. I am not able to decide the logic to prevent my partial view from being directly accessible from URL.

One approach i used is

[HttpPost]
public IActionResult Search(ListNSearchModel modelMain)
{ //....some logic...
 return PartialView();     
}

This made my code only available through Post Request but i don't think this is correct way.

Upvotes: 0

Views: 1937

Answers (3)

user2496621
user2496621

Reputation: 11

Just add the [ChildActionOnly] above your Action and should prevent user from accesing directly.

**[ChildActionOnly]**
[HttpPost]
public IActionResult Search(ListNSearchModel modelMain)
{ //....some logic...
 return PartialView();     
}

Upvotes: 1

GregH
GregH

Reputation: 5459

You can create an annotation for your controller action that will prevent users from accessing it directly. Note that the following should work whether the request is coming from ajax or not (could just be calling out to an action to return a partial view via html helpers):

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class NoDirectAccessAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.UrlReferrer == null ||
                    filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
            {
            filterContext.Result = new RedirectToRouteResult(new
                           RouteValueDictionary(new { controller = "Home", action = "Index", area = "" })); 
        }
    }
}

then annotate your controller action with it as follows:

[HttpPost]
[NoDirectAccess]
public IActionResult Search(ListNSearchModel modelMain)
{ 
     return PartialView();     
}

Upvotes: 2

Nan Yu
Nan Yu

Reputation: 27578

The X-Requested-With header returns a string that indicates whether it's an Ajax request or not. An Ajax request will have this header set to XMLHttpRequest. This header value won't be present for normal GET and POST requests (non-Ajax requests).

So you could just write attribute like:

public class AjaxOnlyAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor actionDescriptor)
    {
        if (routeContext.HttpContext.Request.Headers != null &&
          routeContext.HttpContext.Request.Headers.ContainsKey("X-Requested-With") &&
          routeContext.HttpContext.Request.Headers.TryGetValue("X-Requested-With", out StringValues requestedWithHeader))
        {
            if (requestedWithHeader.Contains("XMLHttpRequest"))
            {
                return true;
            }
        }

        return false;
    }
}

Then use that like :

[AjaxOnlyAttribute]
public IActionResult Search()
{

    return PartialView();
}

Or you can directly check that in specific action :

string method = HttpContext.Request.Method;

string requestedWith =
    HttpContext.Request.Headers["X-Requested-With"];

if (method == "POST")
{
    if (requestedWith == "XMLHttpRequest")
    {
        // code goes here
    }
}

Upvotes: 1

Related Questions