Here's my route:
routes.MapRoute("Login", "", new { action = "Login", controller = "Authentication"})
.DataTokens = new RouteValueDictionary(new { area = "Authentication" });
routes.MapMvcAttributeRoutes();
Here is the controller with action:
[RouteArea("Authentication", AreaPrefix = "auth")]
[Route("{action=Login}")]
public class AuthenticationController : BaseController
{
[HttpGet]
[AllowAnonymous]
public ActionResult Login()
{
...
If I comment out routes.MapMvcAttributeRoutes(); then I can request the Login action using '/'. If its left in then this route doesn't work and I get a 404.
How do I make the default route for the website be the login page form the area?
The area is being registered independently of the attributes.
I removed the convention route and added the following to <system.web> in web.config:
<urlMappings enabled="true">
<clear />
<add url="~/" mappedUrl="~/auth" />
</urlMappings>
Related
For the last few days I was looking for a viable solution in order to optimize html page titles <title>SOME_TITLE</title> within sails.js layout files, like layout.ejs, that by default use a static page title.
Obviously, it would be way better to have dynamic page titles, e.g. Dashboard, Shopping Cart, etc...
Other people were looking for this answer before and got answers for prior sails versions in Solution 1, Solution 2 and Solution 3.
Unfortunately, none of them seem to be appropriate for the latest version of sails.js (as of this post).
Solution 1 was leading in the right direction and suggested what I was looking for. But you had to define a title for every controller and pass it into the view. Otherwise you will get
title is not defined at eval
So how to define a local variable that is accessible in each controller/view by default?
So one working complete solution for the current sails.js version is the following:
In your layout.ejs file define a dynamic page title like this
<head>
<title>
<%= title %>
</title>
...
</head>
...
Create a new custom hook, e.g. api/hooks/dynamic-page-title/index.js
module.exports = function dynamicPageTitleHook(sails) {
return {
routes: {
/**
* Runs before every matching route.
*
* #param {Ref} req
* #param {Ref} res
* #param {Function} next
*/
before: {
'/*': {
skipAssets: true,
fn: async function(req, res, next){
// add page title variable to each response
if (req.method === 'GET') {
if (res.locals.title === undefined) {
res.locals.title = 'plusX';
}
}
return next();
}
}
}
}
};
};
Now overwrite the page title in every controller that should use a custom page title, e.g. view-login.ejs
module.exports = {
friendlyName: 'View login',
description: 'Display "Login" page.',
exits: {
success: {
viewTemplatePath: 'pages/entrance/login',
},
redirect: {
description: 'The requesting user is already logged in.',
responseType: 'redirect'
}
},
fn: async function (inputs, exits) {
if (this.req.me) {
throw {redirect: '/'};
}
return exits.success({title: 'Login'});
}
};
module.exports = {
friendlyName: 'View homepage or redirect',
description: 'Display or redirect to the appropriate homepage, depending on login status.',
exits: {
success: {
statusCode: 200,
description: 'Requesting user is a guest, so show the public landing page.',
viewTemplatePath: 'pages/homepage'
},
redirect: {
responseType: 'redirect',
description: 'Requesting user is logged in, so redirect to the internal welcome page.'
},
},
fn: async function () {
if (this.req.me) {
throw {redirect:'/welcome'};
}
return {title: 'Home page'};
}
};
e.g: return (title: 'Home page')
I use version 1.4 of sails
I have add to the file layout.ejs the following code
<% if (typeof pagetitle=="undefined"){%>
<title>write your default title</title>
<% }else{%>
<title><%= pagetitle %></title>
<%}%>
<% if (typeof pagemetadescription=="undefined"){%>
<mеtа nаmе="dеѕсrірtіоn" соntеnt="write your default metadescription"></mеtа>
<% }else{%>
<mеtа nаmе="dеѕсrірtіоn" соntеnt="<%= pagemetadescription %>"></mеtа>
<%}%>
If in controller, i return variable pagetitle or pagedescription, they will be add to layout. Otherwise, the default value will be print.
so I'm currently looking into Neos CMS and wanted to create a very basic login logic. [for practice]
I basically followed: http://flowframework.readthedocs.io/en/stable/TheDefinitiveGuide/PartIII/Security.html#authentication
My Code: [neos/ being the root dir]
Routes: [neos/Configuration/Routes.yaml] Note that's what I added in the beginning of the file, not the whole content of the file.
-
name: 'Authentication'
uriPattern: 'authenticate'
defaults:
'#package': 'VMP.Auth'
'#controller': 'Authentication'
'#action': 'authenticate'
AuthenticationController.php [neos/Packages/Plugins/VMP.Auth/Classes/VMP/Auth/Controller/]
<?php
namespace VMP\Auth\Controller;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Mvc\ActionRequest;
use TYPO3\Flow\Security\Authentication\Controller\AbstractAuthenticationController;
class AuthenticationController extends AbstractAuthenticationController {
/**
* Displays a login form
*
* #return void
*/
public function indexAction() {
}
/**
* Will be triggered upon successful authentication
*
* #param ActionRequest $originalRequest The request that was intercepted by the security framework, NULL if there was none
* #return string
*/
protected function onAuthenticationSuccess(ActionRequest $originalRequest = NULL) {
if ($originalRequest !== NULL) {
$this->redirectToRequest($originalRequest);
}
$this->redirect('someDefaultActionAfterLogin');
}
/**
* Logs all active tokens out and redirects the user to the login form
*
* #return void
*/
public function logoutAction() {
parent::logoutAction();
$this->addFlashMessage('Logout successful');
$this->redirect('index');
}
public function fooAction() {
print "lol";
}
}
NodeTypes.yaml [neos/Packages/Plugins/VMP.Auth/Configuration/]
'VMP.Auth:Plugin':
superTypes:
'TYPO3.Neos:Plugin': TRUE
ui:
label: 'Auth Login Form'
group: 'plugins'
Policy.yaml [neos/Packages/Plugins/VMP.Auth/Configuration/]
privilegeTargets:
'TYPO3\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':
'VMP.Auth:Plugin':
matcher: 'method(TYPO3\Flow\Security\Authentication\Controller\AbstractAuthenticationController->(?!initialize).*Action()) || method(VMP\Auth\Controller\AuthenticationController->(?!initialize).*Action())'
roles:
'TYPO3.Flow:Everybody':
privileges:
-
# Grant any user access to the FrontendLoginLoginForm plugin
privilegeTarget: 'VMP.Auth:Plugin'
permission: GRANT
Settings.yaml [neos/Packages/Plugins/VMP.Auth/Configuration/]
TYPO3:
Neos:
typoScript:
autoInclude:
'VMP.Auth': TRUE
Flow:
security:
authentication:
providers:
'AuthAuthenticationProvider':
provider: 'PersistedUsernamePasswordProvider'
Index.html [neos/Packages/Plugins/VMP.Auth/Resources/Private/Templates/Authentication/]
<form action="authenticate" method="post">
<input type="text"
name="__authentication[TYPO3][Flow][Security][Authentication][Token][UsernamePassword][username]" />
<input type="password" name="__authentication[TYPO3][Flow][Security][Authentication][Token][UsernamePassword][password]" />
<input type="submit" value="Login" />
</form>
**Root.ts2 [neos/Packages/Plugins/VMP.Auth/Resources/TypoScript/]
prototype(VMP.Auth:Plugin) < prototype(TYPO3.Neos:Plugin)
prototype(VMP.Auth:Plugin) {
package = 'VMP.Auth'
controller = 'Authentication'
action = 'index'
}
Problem:
if I call: www.neos.dev/authenticate I get:
Validation failed while trying to call VMP\Auth\Controller\AuthenticationController->authenticateAction().
So I think, the route itself does work. I now added the login form of my VMP.Auth Plugin to some page and logged in (with an existing user). The login form uses /authenticate as its action, but now I get the following error:
Page Not Found
Sorry, the page you requested was not found.
#1301610453: Could not resolve a route and its corresponding URI for the given parameters. This may be due to referring to a not existing package / controller / action while building a link or URI. Refer to log and check the backtrace for more details.
I don't really know what's the issue here. I guess my routing is wrong but I can't see it.
your onAuthenticationSuccess method has:
$this->redirect('someDefaultActionAfterLogin');
which is probably triggered (correctly) now. That tries to redirect to an action someDefaultActionAfterLoginAction in your AuthenticationController but this action does not exist. For starters try
$this->redirectToUri('/') to just have a redirect to the homepage.
So I've set up everything to invite users to the registration page on my site and track their invitation code, but now whenever a user accepts the invitation they end up getting the following error:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
And here's the URL:
http://www.facebook.com/dialog/oauth/?state=eyJyIjoiaHR0cDovL2FwcHMuZmFjZWJvb2suY29tL2Zpc2hhcndlLz9yZXF1ZXN0X2lkcz0xMDE1MDYzNzQzNDI4NTQ4NCwxMDE1MDYzNzU3NjA0MDQ4NCwxMDE1MDYzNzU4MDQ1NTQ4NCwxMDE1MDYzNzU5NzQ2MDQ4NCwxMDE1MDYzNzYxNDUyMDQ4NCwxMDE1MDYzNzYzMDg0NTQ4NCZyZWY9bm90aWYmbm90aWZfdD1hcHBfcmVxdWVzdCJ9&client_id=217174461634478&redirect_uri=http://www.fisharwe.com/facebookredirect.axd
Why is the redirect_uri http://www.fisharwe.com/facebookredirect.axd and not what I've set in my code using top.location.href="whatever.com"?
UPDATE:
Seems like that problem has been resolved somehow. But it still does not redirect to the registration page of my site! Here's the source code of the landing page:
<html><head><script type="text/javascript">
top.location = "http://www.facebook.com/dialog/oauth/?state=eyJyIjoiaHR0cDovL2FwcHMuZmFjZWJvb2suY29tL2Zpc2hhcndlLz90eXBlPWRpc2NvdmVyeSJ9&client_id=217174461634478&redirect_uri=http://www.fisharwe.com/facebookredirect.axd";
</script></head><body></body></html>
UPDATE2:
This is my C# code:
[CanvasAuthorize]
public ActionResult Index()
{
var fb = new FacebookWebClient(FacebookWebContext.Current);
dynamic requestInfo = fb.Get("/me/apprequests/");
var b = requestInfo.Count;
if (requestInfo.data.Count > 0)
{
var a = requestInfo["data"][0]["data"];
//ViewData.Add("TrackingData", a);
return Redirect(redirectUrl + "?code=" + a);
}
return RedirectToAction("Index", "Home");
}
have you setup the http handler in web.config?
<httpHandlers>
<add verb="*" path="facebookredirect.axd" type="Facebook.Web.FacebookAppRedirectHttpHandler, Facebook.Web" />
</httpHandlers>
I am implementing a simple ExtJS form that submits to a Struts 2 ActionSupport class. The code for the various components is as follows:
MyAction.java:
//packaging and imports
public class MyAction extends ActionSupport {
private String aField;
private String anotherField;
public String execute() throws Exception {
System.out.println(afield + " " + anotherField); //just checking values, atm
return ActionSupport.SUCCESS;
}
public String getAField() {
return this.aField;
}
public void setAField(String aField) {
this.aField = aField;
}
public String getAnotherField() {
return this.anotherField;
}
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
}
myForm.js:
Ext.onReady(function() {
Ext.QuickTips.init();
// turn on validation errors beside the field globally
Ext.form.Field.prototype.msgTarget = 'side';
var myForm = new Ext.form.FormPanel({
id: 'myFormId',
url: 'submitMyForm.action',
defaults: {
xtype: 'textfield'
},
items: [
{
fieldLabel: 'A Field',
id: 'aField',
name: 'aField',
allowBlank: false
},
{
fieldLabel: 'Another Field',
id: 'anotherField',
name: 'anotherField',
allowBlank: false
}
],
renderTo: 'contentMain'
});
var submitButton = new Ext.Button({
text: 'SUBMIT',
handler: function(button, event) {
myForm.getForm().submit({
url: 'submitMyForm.action',
failure: function() {
Ext.Msg.alert('Error', 'Can not save data.');
}
});
}
});
});
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="myPackage" namespace="/" extends="json-default">
<action name="submitMyForm" class="mycodepackage.MyAction">
<result name="*" type="json">
<param name="includeProperties">aField</param>
</result>
</action>
</package>
</struts>
When the submit button is pressed, my action executes properly, and in addition to standard debugging data prints out:
null null
The JSON result is sent back correctly, but of course is also null:
14:22:17,046DEBUG JSONResult:68 - Adding include property expression: aField
14:22:17,052DEBUG JSONWriter:68 - Ignoring property because of include rule: anotherField
14:22:17,053DEBUG JSONUtil:68 - [JSON]{"aField":null}
Now, it's my understanding that the values entered in the form should be inserted into the instance variables for my action class. Am I wrong in this? If not, what could be going wrong? If so, what can I do to ensure that the form data is sent to my action handler?
Thanks.
Any parameters sent will be placed into the similarly named setters. Why don't you first check that the form parameters are getting sent correctly with LiveHttpHeaders Firefox plugin.
Once we realized the form data was not being correctly passed into the http request, my coworker developed a form data interceptor, which we use to load the data in manually. For more information, look into the <interceptor>, <interceptor-stack>, and <interceptor-ref> tags.
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