Is it possible to turn off ssl at the controller level of an ASP.Net MVC application? - asp.net-mvc-2

Is there a way maybe via an action filter to turn off ssl for specific methods?
Example...if someone somehow hits my Index method and has ssl on...can I redirect to the method again and turn it off?

Global.asax.cs
protected void Application_BeginRequest(){
if (Context.Request.IsSecureConnection)
Response.Redirect(Context.Request.Url.ToString().Replace("https:", "http:"));
}
You could add the same code to an action filter:
public class SSLFilter : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext){
if (filterContext.HttpContext.Request.IsSecureConnection){
var url = filterContext.HttpContext.Request.Url.ToString().Replace("https:", "http:");
filterContext.Result = new RedirectResult(url);
}
}
}

Related

.Net core controller tempdata add/remove

Implementing ExceptionFilterAttribute OnException method and need to redirect
The old implementation (.Net 48) was
exceptionContext.Controller.TempData.Remove("");
exceptionContext.Controller.TempData.Add("");//exception message is added
exceptionContext.Controller.ControllerContext.HttpContext.Response.Redirect(url);
For the redirect I guess I can:
exceptionContext.HttpContext.Response.Redirect(url);//Is this correct?
Please suggest alternate for the remove and add?
In .net 6,there's no exceptionContext.Controller.TempData if you want to access TempData in your ExceptionFilter,you could try to inject the TempdataDictionaryFactory into the filter
For example, I tried as below:
public class MyExceptionFilter : ExceptionFilterAttribute
{
private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;
public MyExceptionFilter(ITempDataDictionaryFactory tempDataDictionaryFactory)
{
_tempDataDictionaryFactory = tempDataDictionaryFactory;
}
public override void OnException(ExceptionContext context)
{
var tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
tempData.Add("key", "value");
context.Result = new RedirectToActionResult("Error", "Home", null);
}
}
in Program.cs:
builder.Services.AddControllersWithViews(x=>x.Filters.Add(typeof(MyExceptionFilter)));
The Result:

How to override route in a plugin nopcommerce

I've a route like Admin/Vendor in my MVC application . Without changing this route I need to point this same route to another method say CustomAdmin/CustomVendor.
I tried attribute routing but no luck . Is there any way to do this. My current code is given below
Original Method:
public class AdminController
{
public ActionResult Vendor()
{
return View();
}
}
Custom Method:
public class CustomAdminController
{
[Route("Admin/Vendor")]
public ActionResult CustomVendor()
{
return View();
}
}
As you're developing a plugin. You have to add your custom route to the RouteProvider.
In default nopCommerce AdminController and Vendor doesn't exists, so I assume that you're trying to override vendor list method of admin.
Which looks like:
public partial class RouteProvider : IRouteProvider
{
public void RegisterRoutes(RouteCollection routes)
{
var route = routes.MapRoute("Plugin.GroupName.PluginName.CustomVendor",
"Admin/Vendor/List",
new { controller = "CustomAdminController", action = "CustomVendor", orderIds = UrlParameter.Optional, area = "Admin" },
new[] { "Nop.Plugin.GroupName.PluginName.Controllers" });
route.DataTokens.Add("area", "admin");
routes.Remove(route);
routes.Insert(0, route);
}
public int Priority
{
get
{
return 100; // route priority
}
}
}
Side Note: GroupName and PluginName should be your plugin group name and plugin name.
Hope this helps !
On your plugin which class implements the interface IRouteProvider, you can easily override the route there.
Likewise I have a class named RouteProvider in my plugin, So I have Implemented the abstract function RegisterRoutes and simply it can be overrided by
routes.MapRoute("Plugin.Promotion.Combo.SaveGeneralSettings",
"Admin/Vendor",
new { controller = "CustomAdmin", action = "CustomVendor", },
new[] { "Nop.Plugin.Promotion.Combo.Controllers" }
);
Here Plugin.Promotion.Combo must be replaced by your plugin directory.And using SaveGeneralSettings or any things you want to use that will be your route url

SignalR issues with SignalR.Ninject and overiding the IConnectionIdFactory

I have all the Nuget Bits for SignalR , I am trying to use my own clientIDs as well as the dependency Injection container that comes with SignalR for all my other repositories and such. Now the strange thing is this jQuery to connect to the hub fails on:
debugger;
// Proxy created on the fly
var chat = $.connection.chat;
Basically, the chat object becomes undefined as if SignalR cannot be resolved. This started happening once I tried to overide the default resolver for SignalR with the code below.
What am I missing here?
Another issue I am having is I am not sure if my UserClientIDfactory which implements IConnectionIdFactory
is working either.
Here is the MVC3 code in my Global.asax
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<UserIdClientIdFactory>()
.To<UserIdClientIdFactory>()
.InRequestScope();
//Rest of the other stuff to inject
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//ninject calls to create the kernal etc
IKernel kernel = CreateKernel();
//TO DO using signal IR resolver
var resolver = new NinjectDependencyResolver(kernel);
SignalR.Hosting.AspNet.AspNetHost.SetResolver(resolver);
}
Finally, here is the code for my custom clientIDfactory
public class UserIdClientIdFactory : IConnectionIdFactory
{
#region IConnectionIdFactory Members
string IConnectionIdFactory.CreateConnectionId(SignalR.Hosting.IRequest request)
{
// get and return the UserId here, in my app it is stored
// in a custom IIdentity object, but you get the idea
return HttpContext.Current.User.Identity.Name != null ?
//TO DO change to get profileID from Appfabric or the database and log user infor
HttpContext.Current.User.Identity.Name.ToString() :
Guid.NewGuid().ToString();
}
#endregion
}
As I read your question you ask how to do proper dependency injection in ASP.NET MVC and SignalR using the same DI container (and hence only need to declare bindings in one place). If this is correct understood, I once wrote a blog post regarding this: http://lcdev.dk/2012/02/14/using-signalr-ninject-with-asp-net-mvc3-and-the-ninject-mvc3-nuget-package/
In the blog post I assume that you are using ASP.NET MVC3 as well as the Ninject.MVC3 and the SignalR.Ninject Nuget packages.
However, if this is not the case I do have a comment to your code. To me it seems like that the kernel used to make your bindings (in RegisterServices) is not the kernel you actually register with SignalR. And if this is the case, then of course SignalR won't know about your intended bindings and might throw an exception as result of your use of an un-instantiated object reference -> which then might explain why you no longer can connect to your SignalR hub.
ok thanks for the your post man, made me do some more digging , I read the rest of the post you linked about how to use Ninject with MVC3 which lead me to realize that I had ninject but not the Nuget Bits for Ninject Mvc3 , I added that and alos modifed my global.asax using the following post
http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/
here is the working code in gloabal.asax I also removed the bootstrapper that NinJect mvc3 added to the application start folder since that is how it works in the above post
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.IgnoreRoute("{*allaxd}", new { allaxd = #".*\.axd(/.*)?" }); //added for mango chat
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
public override void Init()
{
this.AuthenticateRequest += new EventHandler(MvcApplication_AuthenticateRequest);
this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
base.Init();
}
#region "Ninject stuff for dependancy Injection
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
// kernel.Load(Assembly.GetExecutingAssembly());
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<UserIdClientIdFactory>()
.To<UserIdClientIdFactory>()
.InRequestScope();
SignalR.Hosting.AspNet.AspNetHost.DependencyResolver.Register(typeof(IConnectionIdFactory), () => new UserIdClientIdFactory());
}
#endregion
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
//for project awesome
ModelMetadataProviders.Current = new AwesomeModelMetadataProvider();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}

ActionFilterAttribute to turn off SSL on Asp.Net MVC2 controller doesn't work consistently

This Action Filter doesn't seem to work consistently. Some times it turns SSL off and sometimes it doesn't. I have it applied to the entire controller at it's declaration.
public class SSLFilter:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequestBase req = filterContext.HttpContext.Request;
HttpResponseBase res = filterContext.HttpContext.Response;
if (req.IsSecureConnection)
{
var builder = new UriBuilder(req.Url)
{
Scheme = Uri.UriSchemeHttp,
Port = 80
};
res.Redirect(builder.Uri.ToString());
}
base.OnActionExecuting(filterContext);
}
}
It's kind of odd...any ideas why it might be working sporadically?
Have you tried decorating your controllers/actions with the [RequireHttps] attribute?
Oops, haven't noticed you was asking about ASP.NET MVC 2. This attribute is available in ASP.NET MVC 3 only, so here's the source code for it (as implemented in ASP.NET MVC 3):
using System;
using System.Diagnostics.CodeAnalysis;
using System.Web.Mvc.Resources;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter {
public virtual void OnAuthorization(AuthorizationContext filterContext) {
if (filterContext == null) {
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.Request.IsSecureConnection) {
HandleNonHttpsRequest(filterContext);
}
}
protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) {
// only redirect for GET requests, otherwise the browser might not propagate the verb and request
// body correctly.
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
}
// redirect to HTTPS version of page
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}
Notice that how instead of doing any redirects it uses a RedirectResult which is the correct way of performing redirects in ASP.NET MVC => by returning action results:
filterContext.Result = new RedirectResult(url);
Not only that this will perform the correct redirect but that's how to short-circuit the execution of an action. Also semantically your filter should actually be an IAuthorizationFilter as you are blocking access to some resource here.

How can I change a route value then redirect to that route?

I have a UserAccountController that takes routes like this "/{username}/{action}".
I'd like to create some functionality so that I can take a user to an account-specific page without knowing their username up front. I'd like to be able to use the URL "/your/{action}" which would catch the fact that "your" was sent as their username, get their real username (because they are logged in), and redirect them to "/their-actual-username/{action}".
I could do this in each of the controller actions, but I'd rather have it happen some place earlier that would do this for all of the controller actions. I attempted to do this in the Controller's Initialize method by changing the RouteData.Values["username"] to the real username then attempting to Response.RedirectToRoute(RouteData); Response.End() but that always took me to the wrong place (some completely wrong route).
Updated:
Thanks to BuildStarted for leading me to this answer:
public class UserAccountController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
if ((string) filterContext.RouteData.Values["username"] != "your")
return;
var routeValues = new RouteValueDictionary(filterContext.RouteData.Values);
routeValues["username"] = UserSession.Current.User.Username;
filterContext.Result = new RedirectToRouteResult(routeValues);
}
}
You can use the FilterAttribute with IActionFilter to accomplish what you want.
public class UserFilterAttribute : FilterAttribute, IActionFilter {
public void OnActionExecuted(ActionExecutedContext filterContext) {
}
public void OnActionExecuting(ActionExecutingContext filterContext) {
var username = filterContext.RouteData.Values["username"];
var realUserName = ""; //load from database
filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new { controller = "Users", action = "Index", username = realUserName }));
}
}
Then on your ActionResult in your controller you could apply [UserFilter] to the action.
[UserFilter]
public ActionResult UnknownUserHandler() {
return View();
}
This should get you the results you're looking for. Any questions please post :)