I'm having an issue with exceptions showing app as stack traces in the page.
I thought that I had mitigated this by adding this to the web.config:
<customErrors mode="On" defaultRedirect="~/error/GenericError">
<error statusCode="403" redirect="~/error/NoAccess" />
<error statusCode="404" redirect="~/error/NotFound" />
</customErrors>
It works for non-existent routes, but not when a controller throws an exception. Here's the Controller logic:
[HandleError]
public class DebugController : Controller
{
public ActionResult Index()
{
throw new Exception("** Testing custom error Handling **");
return View();
}
}
public class ErrorController : Controller
{
//
// GET: /Error/
public ActionResult NotFound()
{
ViewData["error"] = "That page does not exist.";
return View();
}
public ActionResult GenericError()
{
if (null == TempData["error"]))
{
ViewData["error"] = "We're sorry, but an error has occurred.";
}
else
{
ViewData["error"] = TempData["error"];
}
return View();
}
public ActionResult NoAccess()
{
ViewData["error"] = "You are not authorized to access application";
return View();
}
}
And here's the View:
<%# Page Title="" Language="C#"
MasterPageFile="~/Views/Shared/CenterContentNoSidebar.Master"
Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
GenericError
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>An Error has occurred</h2>
<br />
<%= ViewData["error"] %>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="NavContent" runat="server">
</asp:Content>
Do I have to put something in the Global.asax to make this work?
So The HandleError Attribute is actually handling the error and trying to return an Error.aspx view from the controllers view folder or the shared location. The customErrors web.config section is never being hit, and since the page might not exist the yellow screen of death is being displayed anyways. The non-existent routes is working cause IIS is throwing a 404 error and has no context of a controller or HandleError attribute. If you want to handle the errors yourself I would suggest removing the HandleError attributes and let the customErrors some through. From your error controller though you would have to grab the last exception though and do something with it. Here is a good reference on what I am talking about a little.
http://blog.dantup.com/2009/04/aspnet-mvc-handleerror-attribute-custom.html
It is kind of a one or the other type of thing, HandleError attribute or customErrors web.config section.
Your seeing this behavior because of the [HandleError] that you placed on your top line. Please see this qusetion/answer on Stack for more information on the [HandleError] attribute.
StackOverflow Handle Error Q&A
Related
An ASP.NET project is using Crystal Report 13.0. CR component has been added on the page like this
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<CR:CrystalReportViewer ID="CRViewer" runat="server" AutoDataBind="true" HasCrystalLogo="False" HasToggleGroupTreeButton="False" ToolPanelView="None" EnableParameterPrompt="False" Width="100%" Height="100%" />
</asp:Content>
It seems CR inserts following script at runtime (not part of the source code) in the page on report generation
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
The script is not compatible with project's following CSP and hence throwing error Refused to execute inline script because it violates the following Content Security Policy
script-src 'self' 'nonce-abcdefgh' http://localhost:50/ 'unsafe-eval'
What options are there to make it work? Don't want to use unsafe-inline. Could sha256-{hash of the inserted script} be used (haven't tried yet)? Won't it restrict all other scripts? What if CR inserts more scripts in some different conditions?
note: I am new to Play Framework
Using this video tutorial and playlist, I manage to create a simple webapp.
Problem:
POST methods in routes file do not seem to execute the required POST code.
Given the routes file below, browsing to localhost:{port}/user/register requests a GET, thus rendering and returning the register view.
Filling in the register view fields, and clicking submit, refreshes the page (by clearing the input fields) and does show the expected "registered" text
If method="post" has been added to the form in the register view, an immediate 403 Forbidden page page is displayed.
Why isn't the "registered" text being shown, what am I missing (doing wrong) ?
Routes file:
GET / controllers.HomeController.index
GET /user controllers.LoginController.index()
GET /user/login controllers.LoginController.login()
POST /user/login controllers.LoginController.doLogin()
GET /user/register controllers.LoginController.register()
POST /user/register controllers.LoginController.doRegister()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
Controllers:
HomeController
LoginController
LoginController methods:
public Result index() { return ok(views.html.user.index.render(User.getAllUsers())) }
public Result login() { return ok(login.render()); }
public Result doLogin() { return ok("registered"); }
public Result register() { return ok(register.render()); }
public Result doRegister() { return ok("registered"); }
Register View:
#()
<html>
<head>
<title>Register new User</title>
</head>
<body>
<h1>Register User</h1>
<br>
<br>
Enter Email Address: <input type="password" name="confirmPassword">
Enter Password: <input type="password" name="confirmPassword">
Confirm Password: <input type="password" name="confirmPassword">
<br>
<br>
<form action="#routes.LoginController.doRegister()">
<input type="submit" value="Register"/>
</form>
</body>
</html>
Console output error:
[warn] p.filters.CSRF - [CSRF] Check failed because no or invalid token found in body
[warn] p.filters.CSRF - [CSRF] Check failed with NoTokenInBody
I think you're correct you need to define the HTTP method (GET or POST) to be used when submitting the form data.
It's possible you're seen Forbidden because "By default, Play will require a CSRF check" See here?
Add the CSRF token to the request like this:
#import helper._
<form method="post" action="#CSRF(routes.LoginController.doRegister())">
...
Or in the body of the form:
<form method="post" action="#routes.LoginController.doRegister()">
#CSRF.formField
...
I am looking at an example from Spring In Practice. I have the following controller:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/users")
public class AccountController {
private static final Logger LOG = LoggerFactory.getLogger(AccountController.class);
#RequestMapping(value = "/new", method = RequestMethod.GET)
public String getRegistrationForm(Model model) {
model.addAttribute("account", new AccountForm());
return "users/registrationForm";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String postRegistrationForm(AccountForm form) {
LOG.info("Created registration: {}", form);
return "redirect:/users/registration_ok.html";
}
}
The URL "/main/users/new" in this controller creates a new AccountForm object and returns it to the view /main/users/registrationForm. Here is that jsp:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1 /DTD/xhtml1-strict.dtd">
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>New user registration</title>
</head>
<body>
<h1>New user registration</h1>
<form:form cssClass="main" action="." modelAttribute="account">
<p>All fields are required.</p>
.... Form fields here ....
</form:form>
</body>
</html>
The book indicates to use action="." to post the form submission to /main/users. I am wondering if the reason action="." posts to /main/users is because this form was 'called' by a method in a controller mapped to /main/users and the "." specifies to post to this URL? The book does not explain this. Thank you in advance.
. is a relative URI like any other; it points to the current “directory”. In /main/users/new, that’s /main/users/. .. would be /main/.
Consider the case when the action is create instead; you’d end up with /main/users/create. . makes it /main/users/. According to section 5.2.4 of RFC 3986, that becomes /main/users/. (You can find a full description of every step in resolving a relative URI there, too.)
I have an application that in the admin area there is options such as
Background image: [ File Upload ]
Top Illustration: [ File Upload ]
and in the front end I want to easily attach this info to the CSS, maybe teh simply way should be
.background {
background: url(<%: Model.BackgroundUrl %>);
...
}
I currently have my Css files unde ~/Content/Css
shall I have a View with this and change the content type so I can use the Model part?
What other techniques are available or this situation?
Thank you.
You cannot use the model in a static CSS file. If you want to achieve this you will need to generate it dynamically using a controller action. As an alternative you could directly use an img tag:
<img src="<%: Model.BackgroundUrl %>" alt="" />
I ended up doing a new View and set all up as:
in the Master Template
<link href="<%= Url.Content(
String.Format("~/{0}/Css/CustomCss.aspx",
ViewData["CalendarUrl"])) %>"
rel="stylesheet" type="text/css" />
in the Routes
routes.MapRoute(
"CustomCss", // Route name
"{calurl}/Css/CustomCss.aspx", // URL with parameters
new { calurl = "none", controller = "Content", action = "CustomCss", id = UrlParameter.Optional } // Parameter defaults
);
in the Controller: Content, Action: CustomCss
// GET: /Css/CustomCss
public ActionResult CustomCss(string calurl)
{
return View();
}
in my View (placed in Shared):
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>"
ContentType="text/css" %>
<%
string company_logo = ViewData["CompanyLogo"] as string;
string company_bkg = ViewData["CompanyBackground"] as string;
%>
.background {
<%if (!String.IsNullOrWhiteSpace(company_bkg))
{ %>background-image:url('<%: company_bkg %>');<%} %>
}
#header-content{
<%if (!String.IsNullOrWhiteSpace(company_logo ))
{ %>background-image:url('<%: company_logo %>');<%} %>
}
I see it all over the place, yet, I could not find one example about this (maybe I don't know the proper wording), I am trying to build using ASP .Net MVC2 (but any example on just ASP .Net would be also helpful) a process that will send a link to the user at the end of the registration process to let him confirm his registration. Also, a similar process to let the user to reset his password, with the typical "forgot password" and send a link/url so that the user can click and type a new password. Can someone help me to either find an example or at least to let me know how to "google" it?
Thanks,
Mark
For the forgot password, you can make a view like this
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true)%>
<p><%: ViewData["Error"] %></p>
<p> Have you forgotten you password? No problem!</p>
<div class="editor-label">
<%: Html.Label("Fill in your username") %>
</div>
<div class="editor-field">
<%: Html.TextBox("userName") %>
</div>
<p> and <input type="submit" value="click here" /> to reset your password.</p>
<% } %>
and as a controller (first make an model from the aspnetdb (if you don't see it press the 'show all files' button))
This must be placed right after the controller definition
aspnetdbEntities aspnetdb = new aspnetdbEntities();
Then follows this
public ActionResult ForgottenPassword()
{
return View();
}
[HttpPost]
public ActionResult ForgottenPassword(FormCollection formValue)
{
var userName = formValue["userName"];
try
{
var useraccount = aspnetdb.aspnet_Users.Single(c => c.UserName == userName);
var fromAddress = "put an email-address";
var message = new MailMessage(fromAddress, user.Email)
{
Subject = "",
Body = "a link to a controller that lets the user put in a
new password and then save that password to the aspnetdb."
(that controller will most likley require a username)
"or a link with a new random password in it tht you have put
as his password like this:"
useraccount.aspnet_Membership.Password = "random password";
aspnetdb.SaveChanges;
};
var client = new SmtpClient("smtpServerName");
client.Send(message);
return View();
}
catch
{
ViewData["Error"] = "Please give up an existing username";
return View();
}
}
I hope this answer was helpfull.