Is where any attribute in MVC that restricts an action method so that the method handles only accept contentType: 'application/json' requests?
[HttpPost]
public JsonResult GetLastestPosts(int categoryID, int lastPostID)
{
var list = Posts.GetPostsByRootCategoryIDForAjax(categoryID, lastPostID);
return new JsonResult()
{
Data = list
};
}
There isn't any out of box feature which can restrict requests based on ContentType.But you can always write custom Action Filter and make the necessary restrictions there.
public class RestrictionAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//Check for the content type take decision based on that.
}
}
Related
Is it possible to use Feature Toggling in MVC Web APIs?
I want to restrict certain controller actions to be called until the API functionality is complete.
A suggestion could be to create a custom Feature actionfilter. Maybe like this:
public class FeatureAttribute : ActionFilterAttribute
{
public string RequiredFeature { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Settings.Default.SomeFeature)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary {{ "Controller", "Home" }, { "Action", "Index" } });
}
base.OnActionExecuting(filterContext);
}
}
And on your controller add the attribute:
[Feature(RequiredFeature = "Somefeature")]
public ActionResult ActionNotYetReady()
{
return View();
}
This is a simple example, but would redirect users to a specific controller-action whenever the feature toggle/config setting for a given feature is turned off.
I would like to protect my public method from being called by a user.
Because I'm calling the action from an ajax script I can't use any access modifiers, (private, protected etc).
Also, [HttpPost] doesn't stop the user from doing a fake request.
Anyone got a solution?
Thanks
Create an action filter that allows action methods to be called by AJAX only
namespace MyFilters
{
[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 404;
filterContext.Result = new HttpNotFoundResult();
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
}
Then apply this to the action method
[AjaxOnly]
public JsonResult DoSomething()
{
....
In order to disable browser cache, to reliably instructing the browser not to cache, I found the best solution was to create your own [NoCache] attribute class
public class NoCacheSettingsAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
base.OnResultExecuting(filterContext);
}
}
And a global filter settings
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// Makes sure that cached pages are not served to any browser including chrome
filters.Add(new NoCacheSettingsAttribute());
}
I want to use [OutputCache(CacheProfile = "2Hour")] in some ActionResult of a controller and also want to use NoCacheSetting for rest of controller globally , Let say in BaseController, (all controller inherit from BaseController)
So the question is that will it work properly ? Or I have to put rest of controller 1 by one ?
Why not simply exclude controller actions already decorated with the OutputCache attribute from processing:
public class NoCacheSettingsAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var descriptor = new ReflectedControllerDescriptor(
filterContext.Controller.GetType()
);
var action = descriptor.FindAction(
filterContext.Controller.ControllerContext,
filterContext.RequestContext.RouteData.GetRequiredString("action")
);
if (!action.GetCustomAttributes(typeof(OutputCacheAttribute), true).Any())
{
// The controller action is not decorated with the
// [OutputCache] attribute, so you could apply your NoCache logic here
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
}
}
}
If I define an Action filter that implements IActionFilter like so:
public class FooAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{ }
public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Result = new ContentResult
{
Content = "Test",
ContentEncoding = Encoding.UTF8,
ContentType = "text"
};
}
}
And apply it to the following action method:
[Foo]
public ActionResult Index()
{
return View();
}
When I do this the Index action code does not run and neither does the OnResultExecuted method. Is this because I set the Result property in the OnActionExecuting method? Are there any other things that will cause the normal flow to be interrupted?
I think its just the Result property that has this effect..
See here : http://books.google.be/books?id=gzfFQrs_qQAC&lpg=PA442&ots=EXCefpt5-O&dq=iactionfilter%20onactionexecuting&pg=PA442#v=onepage&q=iactionfilter%20onactionexecuting&f=false
User can cancel the action by setting Result to something non-null
[ApiBasicAuthorize]
public ActionResult SignIn()
{
}
I have this custom filter called ApiBasicAuthorize. Is it possible to access ApiBasicAuthorize's data (properties etc) inside the controller action SignIn?
If not, how do I pass data from the filter to controller action?
There is a dictionary called items attached to the HttpContext object. Use this dictionary to store items shared across components during a request.
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.HttpContext.Items["key"] = "Save it for later";
base.OnAuthorization(filterContext);
}
Then anywhere in your code later in the request...
var value = HttpContext.Current.Items["key"];
public override void OnAuthorization(AuthorizationContext filterContext)
{
var rd = filterContext.RouteData;
//add data to route
rd.Values["key"]="Hello";
base.OnAuthorization(filterContext);
}
public ActionResult(string key)
{
//key= Hello
return View();
}