I am converting an asp.net application into mvc3. Lets say I have a sign in page that requires https and every other page only needs http how can I redirect the signin to https and keep all the other pages on http?
Any suggestions would be great!
The RequireHttpsAttribute class may be what you want.
[RequireHttps]
public ActionResult SignIn() {
return View();
}
I like this solution because:
1. Cause you never have to touch it again in VS. The decorator by itself causes the browser to render the site in https even in debug.
If you implement it into a base controller and have all your controllers inherit from that controller, you know there is no slipping in the back do "So to speak".
#if !DEBUG
#define RELEASE
#endif namespace ProjectName.UI.Controllers {
using System.Web.Mvc;
#if RELEASE
[RequireHttps]
#endif
public abstract partial class ProjectNameBaseController : Controller
{
}
}
A co-worker of mine and I looked at this and believe we found a good solution. Here is what we came up with:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class HttpsRequiredAttribute : RequireHttpsAttribute
{
protected override void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
// Check to see if we're secure
string requirestr = ConfigurationManager.AppSettings["RequireHttps"];
bool require;
if (bool.TryParse(requirestr, out require) && require)
base.HandleNonHttpsRequest(filterContext);
}
}
This works by extending the RequireHttpsAttribute, and can be applied to a class or method, as indicated by the AttributeTargets. We then overrode the virtual function in RequireHttpsAttribute. What the method does is check the Web.config file for a key called "RequireHttps". If it cannot find it, or it's an invalid bool value (which is what the bool.tryparse checks), then it does not require Https. If it finds the value as true, then it requires HTTPS.
If you use this extension, you'll need to add a key in your Web.config called "RequireHttps," like so:
<add key="RequireHttps" value="true"/>
You can then turn off the requirement for Https by changing this variable for when you're debugging, or by changing your Web.config file to have the requirement wherever your site is deployed.
the issue is that after log in all your requests are going to be https even if you don't want it
Related
I have an asp.net core 2 webapi service. I want to read appsettings.json but I cannot figure it out. As usual, when I search the internet I get a dozen completely different answers based on various versions of the framework that ultimately don't seem to work.
As an example appsettings.json:
"AppSettings": {
"Domain": "http://localhost"
}
Firstly I tried this:
Added via nuget Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.Json
In my ConfigureServices method I added:
services.AddSingleton<IConfiguration>(Configuration);
In my Controller I injected the config:
IConfiguration iconfig;
public ValuesController(IConfiguration iConfig)
{
iconfig = iConfig;
}
To retrieve it:
return "value: " + iconfig.GetValue<string>("AppSettings:Domain");
I can see the controller constructor being called and passing in a config, but the value is always null.
I did notice that Startup already passes in an IConfiguration. Is it a case of yet another change in implementation and i need to do something different?
[edit]
I've now read
https://joonasw.net/view/aspnet-core-2-configuration-changes
Which says it's all change again and it's auto injected, but after following the code it doesn't actually say how you get your hands on the data in your controller.
You can take a look at my answer here: https://stackoverflow.com/a/46940811/2410655
Basically you create a class that matches the properties you define in appsettings.json file (In the answer it's the AppSettings class).
And then in ConfigureServices(), you inject that class using services.Configure<>. That class will be available in all Controllers by DI.
To access its data, you can take a look at #aman's original question post from the link above.
public class HomeController : Controller
{
private readonly AppSettings _mySettings;
public HomeController(IOptions<AppSettings> appSettingsAccessor)
{
_mySettings = appSettingsAccessor.Value;
}
}
I am using MVC 6 web api and I have a method (shown below). When the user is not authenticated (logged on) and makes the call (example url: https://localhost:44338/api/account/Test), they get automatically pushed to url:
https://localhost:44338/Account/Login?ReturnUrl=%2Fapi%2Faccount%2FTest
BUT this is a web api project and does not have any views (such as im automatically getting pushed to here).
Code:
[HttpGet("test")]
[Authorize]
public async Task<IActionResult> Test()
{
return Json("success");
}
Why am I getting automatically pushed to the login page? I've NOTHING in my startup.cs or web.config that specifies this. It seems like default behaviour? How do I disable this so I just get the 401 status?
Thanks in advance!
For convenience, here's the solution that worked for me:
services.Configure<IdentityOptions>(o =>
{
o.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = ctx =>
{
if (ctx.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
return Task.FromResult<object>(null);
}
ctx.Response.Redirect(ctx.RedirectUri);
return Task.FromResult<object>(null);
}
};
});
I was pointed to this article: mvc6 unauthorized results in redirect instead by #TrevorWard
ASP.NET automatically redirects to the login page, if you have AuthorizationAttribute defined in your App_Start/FilterConfig.cs, see if AuthorizeAttribute() is defined. If it does, remove it.
Check if you have App_Start/Startup.Auth.cs. If it does, delete it.
If Startup.cs is decorated with the attribute [assembly: OwinStartupAttribute(typeof(FleetSys.Startup))], remove that attribute.
You are probably using wrong Authorize attribute.
In MVC, you should use System.Web.Mvc.AuthorizeAttribute and that one will redirect.
In Web API, you should use System.Web.Http.AuthorizeAttribute and that one will return 401 status code.
I have visual studio 2012 installed with mvc4 using .net framework 4.5. Now I want to use webapi2 with attribute writing and i want my hlep page show all the endpoints properly.
In my solution i added a new mvc4 base emtpy project and using nuget i upgraded to mvc5 and then i have installed webapi2 packages. lastly i have installed help package for webapi2.
now when i use routeprefix I cant see any content on help page and when i try to access my webapi endpoint in browsers it throws following error.
http://expressiis.com/api/v1/
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://expressiis.com/api/v1/'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'v1'.
</MessageDetail>
</Error>
namespace WebApi.Controllers
{
[RoutePrefix("api/v1")]
public class SubscribersController : ApiController
{
// GET api/<controller>
[Route("")]
[HttpGet]
public IQueryable<string> Get()
{
return new string[] { "value1", "value2" }.AsQueryable();
}
}
}
Based on your information, it looks like you are not calling the httpConfig.MapHttpAttributeRoutes() (Make sure to call this before any traditional routing registrations)
Since you haven't called MapHttpAttributeRoutes, your request seems to be matching a traditional route, for example, like api/{controller}. This will not work because routes matching traditional routes will never see controllers/actions decorated with attribute routes.
A problem I ran into was related to the ordering in Application_Start(). Note the order of Web API configuraton below:
This does NOT work
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
This does work
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I had this problem too and after a long search I realized that I was using System.Web.Mvc.RouteAttribute instead of System.Web.Http.RouteAttribute
After correcting this and using config.MapHttpAttributeRoutes() everything worked fine.
This was not your case (as is apparent from your sample code), but please do remember to end the Controller class name with Controller.
Else it won't be picked up by config.MapHttpAttributeRoutes();.
This question already has a selected answer. But I had a different solution for myself and think it would be helpful to reply if the selected answer doesn't help.
For me it was a silly mistake. I had two controllers but only one was working. The solutions was that my controller class was named improperly!
My working controller-
public class FooController : ApiController { }
My non-working controller-
public class BarControllers : ApiController { }
Be sure your controller class ends in Controller. The trailing s got me!
Make sure you don't have two controllers with the same name! I was moving some controllers from one assembly I was throwing away into the website... whilst the website no longer had references to the old assembly other assemblies did which meant it was copied in to the WebSite bin folder. The route discovery process then seemed to fail silently when it came across two occurrences of the same controller!
In my case, VS create my controller with the name
TestController1
I dont know why he put this number "one" in the end of name, but remove and will work.
In my case, I was missing full custom path in attributes. I was writing only custom action name without 'api/'. So that was my mistake. My scenario was,
WebApiConfig template code:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
my incorrect way of route
[RoutePrefix("myapps")] // wrong code
public class AppsController : BaseRestAPIController
{
[HttpPost]
[Route("getapps")]
public ResponseData GetAppList()
{
Correct way
[RoutePrefix("api/myapps")] // correct way. full path start from 'api/'
public class AppsController : BaseRestAPIController
{
[HttpPost]
[Route("getapps")]
[Route("api/myapps/getapps")] // you can use full path here, if you dont want controller level route
public ResponseData GetAppList()
{
In my case following line was creating problem, just commented it and everything start working
config.MapHttpAttributeRoutes();
Comment it in WebApiConfig.cs file
I'm having problems with requests that include 'dangerous characters' as part of a Web API URL. The Url includes an & which is properly Url encoded, but still causes a Request Validation ASP.NET error.
Unlike MVC there appears to be no [ValidateInput(false)] attribute to force and disable this functionality.
Turns out the answer is to do this in web.config using:
<system.web>
<httpRuntime requestPathInvalidCharacters="" />
</system.web>
You can set this globally or at the sub-directory level. You can leverage the <location path=""> element to specify this setting only underneath certain paths. For example, if your Web API route that was affected lived underneath api/images you could do the following:
<location path="api/images">
<system.web>
<httpRuntime requestPathInvalidCharacters="" />
</system.web>
</location>
More information: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx
With RequestValidation set to 4.0 in the configuration the answer is no. You can however revert back to 2.0 Request Validation in which case the MVC attribute works as you would expect: Validate by default and explicitly override when needed.
<httpRuntime executionTimeout="300" requestValidationMode="2.0" />
Talked in detail about this and some of the options here:
http://www.west-wind.com/weblog/posts/2010/Aug/19/RequestValidation-Changes-in-ASPNET-40
You can get more fine-grained control over this by setting the requestValidationType attribute of the httpRuntime element to a custom type that inherits from System.Web.Util.RequestValidator and overrides IsValidRequestString.
Unfortunately this isn't part of the WebAPI pipeline, so can't directly check for things like action filters (i.e. attributes on controller methods).
However, if you specifically care about the Validation of Form fields, the Validator doesn't get called on these until you access them, which happens after Action Filters are fired, so you can opt-out of validation using an attribute by creating classes like the following...
public class AllowFormHtmlAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
HttpContext.Current.Items["AllowFormHtml"] = true;
}
}
public class CustomRequestValidator : RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
if (context.Items["AllowFormHtml"] as bool? == true && requestValidationSource == RequestValidationSource.Form)
{
validationFailureIndex = 0;
return true;
}
return base.IsValidRequestString(
context, value, requestValidationSource, collectionKey, out validationFailureIndex);
}
}
... Then just annotating your controller method with [AllowFormHtml]
However, if you're accessing form fields directly from the HttpRequest, it's simpler to use HttpRequest.Unvalidated, which bypasses validation.
per #Levi our Web Security guy:
Config is the only way to do this. Even MVC’s [ValidateInput(false)] wouldn’t help with this particular scenario.
Disabling it in Web.config isn’t necessary a terrible idea. If you’re following good security practice by validating and encoding untrusted data, it’s perfectly fine to apply it application-wide.
I have a situation where T4MVC is generating everything properly (meaning intellisense shows all areas/controllers/actions and everything compiles), but when I run the code, I get a T4MVC was called incorrectly runtime error.
I've investigated the generated files and discovered that for one controller in my project, only actions in the base class are getting the overridden stub actions generated. For other controllers, all actions are being generated. They all have the same set up, described below.
I have a BaseController class that has some shared code (and inherits from Controller). In the Controllers directory (root of project) I have a number of controllers, all which inherit from BaseController.
I then have several Areas. In each Area, I have the same controllers, each inheriting from the controller of the same name in the root Controllers directory.
Running T4MVC (version 2.6.54), everything works fine except for one controller. The odd thing is that intellisense works for the controller, but chokes when the actual action is referenced (in an ActionLink() call).
I manually added one action in particular into the generated code and there was no error.
So my question is, what would cause T4MVC to not generate all code for a controller? The missing actions are all public virtual ActionResult and the actions themselves work fine. The problem controller has the same issue in all Areas.
Some abbreviated code.
/Controllers/BaseController.cs
namespace MyProject.Controllers
{
public abstract partial class BaseController : Controller
{
protected ISession session;
public BaseController()
{
}
// other shared methods/actions
}
}
/Controllers/ActivitiesController.cs (this is the problem controller)
namespace MyProject.Controllers
{
public partial class ActivitiesController : BaseController
{
// for resolving concurrency exceptions
private Activity userValues;
private Activity databaseValues;
public ActivitiesController() : base()
{
ViewBag.ControllerName = "Activities";
}
// this action is causing the problem used like
<li>#Html.ActionLink("Activities", MVC.Areas.Module1.Activities.Index())</li> in a view
public virtual ActionResult Index()
{
return View();
}
}
}
/Areas/Module1/Controllers/ActivitiesController.cs. This is the whole class
namespace MyProject.Areas.Module1.Controllers
{
public partial class ActivitiesController : MyProject.Controllers.ActivitiesController
{
public ActivitiesController() : base()
{
base.currentModule = Modules.Module1;
}
}
}
In case anyone else comes across this I had a similar issue and resulting run-time error message but in a bit different scenario. It was in the RedirectToAction statement at end of a ActionResult method:
RedirectToAction(Edit(id));
The error went away after correcting it to:
RedirectToAction(MVC.[action name].Edit(id));
The error message isn't very intuitive and the suggestion to re-run the custom tool doesn't really help.
Did you make sure to re-run T4MVC to generate based on the latest (Right click .tt file / run custom tool)?
If that's not the problem, I may need to look at a sample app that has the problem to see what's going on.