I created an MVC 5 project and using Windows Authentication.
My problem is whenever an use's action is denied by the action attribute [Authorize(Roles = "Roelabc")], the browser will pop up an login alert with username/passwor.
Now I don't want this pop up, I just want if user is denied then redirect user to an customised page.
Thanks a lot.
Create a class derived from AuthorizeAttribute, will solve my problem.
public class WindowsAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "client", filterContext.RouteData.Values[ "client" ] },
{ "controller", "Home" },
{ "action", "Contact" },
{ "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
});
}
}
}
And use it like this
[WindowsAuthorize(Roles = "User1")]
[HttpGet]
public ActionResult Index(string runDate = "")
{ ... }
You can create a view called unathorized. And in your logon class, just redirect to that view. You can use something like this in logon.cs
if (AuthenticateUser())
{
if (CheckRulesOfBehavior())
{
AuthorizeUser();
HttpContext.Response.Redirect("~/Work/Index");
}
else
{
HttpContext.Response.Redirect("~/Errors/Unauthorized");
}
Related
I have a .NET Core 3.1 project using Razor Pages. From it I created a simple test where I am able to make a successful Ajax call with the following code:
Index.cshtml.cs
public class IndexModel : PageModel
{
public void OnGet()
{
}
public JsonResult OnGetTest()
{
return new JsonResult("Ajax Test");
}
}
Index.cshtml
#page
#model IndexModel
<div class="text-center">
<p>Click here for ajax test.</p>
</div>
<script type="text/javascript">
function ajaxTest() {
$.ajax({
type: "GET",
url: "/Index?handler=Test",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (xhr, status, error) {
console.log(error);
}
}).done(function (data) {
console.log(data);
});
}
</script>
However, I would like to move the Ajax method out of the Razor Page and into to a Controller so I could call it from from multiple Razor Pages. I have created a controller using the following code:
public class AjaxController : Controller
{
public JsonResult Test()
{
return new JsonResult("Ajax Test");
}
}
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
});
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
But whatever value I use in the url for the Ajax call, I get a 404 error. Does the Controllers folder need to be in the Pages directory? Or do I need to configure some routing to use a Controller with Razor Pages?
url: "/Ajax/Test" // <-- What goes here?
Here is the current directory structure:
In Startup.cs, add this to ConfigureServices()
services.AddMvc(options => options.EnableEndpointRouting = false);
In Startupcs, also add this to Configure()
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
DisplayController.cs
public IActionResult Test()
{
return new JsonResult("Hi World");
}
Index.cshtml
<a onclick="ClickMe();">Click Me</a>
<script>
function ClickMe() {
$.get("/Display/Test", null, function (e) {
alert(e);
});
}
</script>
You need to specify a Route attribute, like this:
[Route("api/Ajax")]
public class AjaxController : Controller
{
// ...
}
It is also best to decorate each individual endpoint with a 'Method' attribute, like this:
[HttpGet]
public JsonResult Test()
{
return new JsonResult("Ajax Test");
}
Furthermore you also need to set the correct configuration in Startup.cs as shown below, add all the parts that you do not have:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
});
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// lots of stuff...
// I have this after app.UseStaticFiles(), it may also work elsewhere
app.UseMvcWithDefaultRoute();
// lots of other stuff...
}
And then you should be able to call it using the path /api/Ajax/Test.
I have the following behaviour in my program:
User input for a decimal variable
A) jquery validation turned off:
1) If the user uses a comma as decimal separator, the value is stored correctly in the ViewModel
2) If the user uses a point as decimal separator, the value is multiplied by 100 (as if there was no decimal separator)
B) jquery validation turned on:
1) I get an error, that a number must be supplied
2) same Problem as A2)
However if I display a decimal value of the ViewModel in the view it is shown per default with a point as a decimal separator.
This inconsistency is confusing me and I would like to implement a consistent behaviour, but unfortunately I don't know what I am actually looking for.
The website will be localized in german and italian. The localization works without any problems, so far.
This is my
startup.cs
namespace XXX
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Added - uses IOptions<T> for your settings.
services.AddOptions();
// Added - Confirms that we have a home for our DemoSettings
services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStatusCodePagesWithReExecute("/Error/Index", "?i_statusCode={0}");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
new CultureInfo("de"),
new CultureInfo("it"),
};
var localizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("de"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
};
var requestProvider = new RouteDataRequestCultureProvider();
localizationOptions.RequestCultureProviders.Insert(0, requestProvider);
app.UseRouter(routes =>
{
routes.MapMiddlewareRoute("{culture=de}/{*mvcRoute}", subApp =>
{
subApp.UseRequestLocalization(localizationOptions);
subApp.UseMvc(mvcRoutes =>
{
mvcRoutes.MapRoute(
name: "defaultLocalized",
template: "{culture=de}/{controller=Contract}/{action=Index}/{id?}");
mvcRoutes.MapRoute(
name: "error",
template: "Error/Index",
defaults: new { controller = "Error", action = "Index", culture = "de" });
mvcRoutes.MapRoute(
name: "default",
template: "{*catchall}",
defaults: new { controller = "Home", action = "Index", culture = "de" });
});
});
});
}
}
}
Here i'm new to mvc core2.0 please help me why my Routing Is not working
My Routing Class
public static class ApplicationRoteProfiler
{
public static void Routeing(IRouteBuilder builder)
{
builder.MapRoute("route1", "", new
{
Controllers = "Department",
Action = "Add",
});
builder.MapRoute("route2", "Department/Add", new
{
Controllers = "Department",
Action = "Index"
});
}
This class file i register in startup.config file
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseMvc();
app.UseMvcWithDefaultRoute();
app.UseMvc(routes =>
{
ApplicationRoteProfiler.Routeing(routes);
});
}
When i hit my server as http://localhost:1588/Department/Add its should redirect to Department/Index But its hitting Department/Add
Should it be just Controller not Controllers??
builder.MapRoute("route1", "", new { controller = "department", action = "index" });
My 2 cents
You shouldn't use app.UseMvcWithDefaultRoute() and app.UseMvc() at the same time. You only need to pick 1 of them.
I don't see benefits of using a static class to configure routing for MVC. You can just put all the route configurations right there inside UseMvc lamba function. Also I don't think you need to put customized route specifically for your "route1" as it follows the standard MVC routing convention.
app.UseMvc(routes =>
{
// The order of these routes matters!
routes.MapRoute(
name: "route2",
template: "department/add",
defaults: new { area = "", controller = "department", action = "index" });
routes.MapRoute(
name: "default",
template: "{controller=home}/{action=index}/{id?}");
}
You can also return RedirectToAction("index"); inside your Department controller Add method so whenever /deparment/add route is hit, it redirects to /deparment/index, assuming you have the default MVC routing setup, either use the "default" route I put on #2, or use UseMvcWithDefaultRoute(). That way you don't need to create custom routes just for redirecting.
public class DepartmentController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Add()
{
return RedirectToAction("index");
}
}
I have my first Web API working, but the even when I call it and pass an an id is gets routed to the method that has no arguments.
Here is my controller code:
public class ChartController : ApiController
{
Chart[] _charts = new Chart[]
{
new Chart { Name = "Chart 1" },
new Chart { Name = "Chart 2" },
new Chart { Name = "Chart 3" }
};
// GET api/chart
[Route("api/chart")]
public IEnumerable<Chart> Get()
{
return _charts;
}
// GET api/chart/{id}
[Route("api/chart/{id}")]
public IEnumerable<Chart> Get(int chartId)
{
Chart[] charts = new Chart[]
{
Charts.Database.ChartsDB.GetChart(chartId)
};
return charts;
}
}
Here is my routing in my global.asax
RouteTable.Routes.MapHttpRoute(
name: "ChartApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
This is my request uri
http://localhost:42311/api/chart
And the results
[
{
"Name": "Chart 1"
},
{
"Name": "Chart 2"
},
{
"Name": "Chart 3"
}
]
When I change the uri to
http://localhost:42311/api/chart/1
I get the same results, as both calls are routed to
public IEnumerable<Chart> Get()
What am I doing wrong?
Please note that WebApi works based on reflection this means that your curly braces {vars} must match the same name in your methods.
Therefore to match this api/chart/{id} your method needs to be declare like this:
[Route("api/chart/{chartId}"), HttpGet]
public IEnumerable<Chart> Get(int chartId)
return userId;
}
Where the parameter {id} was replaced by chartId.
Another option can be:
[Route("api/chart/{id}"), HttpGet]
public IEnumerable<Chart> Get(int id)
return userId;
}
If you want to read more about this Routing Rules here is similar post on this;
WebApi Routing Configuration
I'm trying to get ExtDirectSpring to work but can't figure out what the URL to the Direct Router shall be.
My controller:
#Controller
#RequestMapping(value = "/sonstiges/extdirect")
#Transactional
public class ExtDirectController {
#RequestMapping(value = "")
public String start() throws Exception {
return "/sonstiges/extdirect";
}
#ExtDirectMethod(value = ExtDirectMethodType.STORE_READ)
public List<String> loadAllMyStuff() {
return Arrays.asList(new String[] {"one", "two"});
}
}
In my JSP I add a provider like this:
Ext.direct.Manager.addProvider({
"type":"remoting", // create a Ext.direct.RemotingProvider
"url":"/fkr/app/controller/extjs/remoting/router", // url to connect to the Ext.Direct server-side router.
"actions":{ // each property within the actions object represents a Class
"ExtDirectController":[
// array of methods within each server side Class
{
"name":"loadAllMyStuff", // name of method
"len":0
},
{
"name":"myTestFunction", // name of method
"len":0
}
]
},
"namespace":"FKR"// namespace to create the Remoting Provider in
});
... and use the following store to populate a grid:
store: {
model: 'Company',
remoteSort: true,
autoLoad: true,
sorters: [
{
property: 'turnover',
direction: 'DESC'
}],
proxy: {
type: 'direct',
directFn: FKR.ExtDirectController.loadAllMyStuff
}
}
Loading the page, a request to http://localhost:8080/fkr/app/controller/extjs/remoting/router is send, but not to my loadAllMyStuff- function. My guess is that the URL to the direct router is wrong.
What is the correct URL to the router?
EDIT: I just figured out that the method router in RouterController expects the parameters extAction and extMethod, but with the given code the parameters action and method are sent. That seems to be odd ...