Webapi returns html page instead of json - asp.net

I have implemented an action filter attribute for token verification and if token is invalid then api response should return from this action filter.
public class TokenValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
bool isValidToken = FunctionToVerifyToken();
if (!isValidToken ))
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
{
Content = new StringContent("Unauthorized user")
};
return;
}
}
}
Response:
It goes to _layout.cshtml and returns whole html page instead of just returning "Unauthorized user"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Sign in</title>
<link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
<link href="/Content/styles.css" rel="stylesheet"/>
<script src="/Scripts/modernizr-2.8.3.js"></script>
...
Update:
controller where I'm using this token:
public class ServiceController : ApiController
{
[AcceptVerbs("GET", "POST")]
[HttpGet]
[HttpPost]
[TokenValidation]
public object ChangePassword()
{
//my logic is token is valid. It returns json data and works fine.
}
}
The view returned is login page.
My WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{action}/{id}",
defaults: new { controller = "Service", id = RouteParameter.Optional },
constraints: null
);
}
}

In Global.ascx.cs add following line
GlobalConfiguration.Configure(FilterConfig.Register);
In FilterConfig.cs register method
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new TokenValidationAttribute());
}

I think your code are missing this below lines in your TokenValidationAttribute.cs action filter.
base.OnActionExecuting(actionContext); return; What this will do is it would get your formated result and display your result rather than displaying the view.

I returned response as:
actionContext.Response = actionContext.Request.CreateResponse<string>(HttpStatusCode.BadRequest, "Unauthorized user");
and it returned "Unauthorized user" instead of whole html page.

Related

Introductory Spring Boot MVC App - login failed because Could not verify the provided CSRF token because your session was not found

I am trying to write a simple introductory application via Spring Boot, Spring MVC, and Spring Security, but after submitting my Login-form I'm getting redirected a Whitelabel Error Page as a result of a 403 response. The error message is Could not verify the provided CSRF token because your session was not found.
Could anyone please tell me what I'm doing wrong? Should I be disabling CSRF filtering for the login endpoint somehow? And even though it seems to be saying a CSRF token was provided, I don't see one in the request's headers or in the form data... could that be the problem - that I'm not even providing a CSRF token?
/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.5.7.RELEASE'
}
}
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude module: 'spring-boot-starter-tomcat'
}
compile 'org.springframework.boot:spring-boot-starter-jetty'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile 'javax.servlet:jstl:1.2'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.springframework.security:spring-security-test'
}
/src/main/groovy/my.little.app.Application.groovy
#SpringBootApplication
#EnableWebMvc
#EnableAutoConfiguration
#ComponentScan
class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return [WebMvcConfig.class, WebSecurityConfig.class]
}
protected Class<?>[] getServletConfigClasses() {
return [WebMvcConfig.class, WebSecurityConfig.class]
}
protected String[] getServletMappings() {
return [ "/" ]
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
}
/src/main/groovy/my.little.app.MainController.groovy
#Controller
class MainController {
#RequestMapping(path = '/', method = RequestMethod.GET)
public String index() {
return 'index'
}
}
/src/main/groovy/my.little.app.config.WebMvcConfig.groovy
#Configuration
#ComponentScan('my.little.app')
#EnableWebMvc
class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry)
registry.addViewController('/index').setViewName('index')
registry.addViewController('/login').setViewName('login')
registry.addViewController('/secure_page').setViewName('secure_page')
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public ViewResolver internalResourceViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver()
// bean.setViewClass(JstlView.class)
bean.setPrefix('/WEB-INF/views/')
bean.setSuffix('.jsp')
return bean
}
}
/src/main/groovy/my.little.app.config.WebSecurityConfig.groovy
#Configuration
#EnableWebMvc
#EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity security) {
security
.authorizeRequests()
.antMatchers('/', '/index').permitAll()
.antMatchers('/login').anonymous()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage('/login').permitAll()
.defaultSuccessUrl('/secure_page')
.failureUrl('/login?error=true')
.and()
.logout()
.permitAll()
.logoutSuccessUrl('/login')
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) {
authBuilder
.inMemoryAuthentication()
.withUser('doug').password('las').roles('WIZARD')
}
}
/src/main/webapp/WEB-INF/views/index.jsp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Security Tutorial</title>
</head>
<body>
<div>Welcome to the Web Security Tutorial</div>
<form method="get" action="/login">
<input type="submit" value="Sign In" />
</form>
</body>
</html>
/src/main/webapp/WEB-INF/views/login.jsp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Security Tutorial</title>
</head>
<body>
<form method="post" action="login">
<div><label> User name: <input name="username" type="text"/></label></div>
<div><label> Password: <input name="password" type="password"/></label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
/src/main/webapp/WEB-INF/views/secure_page.jsp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Security Tutorial</title>
</head>
<body>
<div>Don't worry, no one can see this but you. Here are your deepest darkest secrets...</div>
<form action="/logout">
<input type="submit" value="Log Out"/>
</form>
</body>
</html>

Viewbag variable in shared view _layout

I would like to use ViewBag values in the shared view of layout but provided from another controller. In particular, I would like to render the principal action and then add few variables, coming from another controller, that are used in a lot of pages (but not in all pages to justify the use of global variables).
Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css_custom")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
#Html.Action("myAction", "myController")
<p>Value: #ViewBag.testval </p>
#RenderBody()
</body>
</html>
Controllers/myController.cs
namespace myProject.Controllers
{
public class myController : Controller
{
public void myAction() {
string test_value = "Hey!";
ViewBag.testval = test_value;
}
}
}
In the layout the only Viewbag variables that I can access are the ones of the action target of RenderBody.
You should return that view.
public ActionResult Index()
{
ViewBag.testval = "Test value";
return View();
}

Putting a model on every view

I'm trying to pass my UserModel to every view, so it can show on top the current user information.
This is my BaseViewModel:
public class BaseViewModel
{
public UserModel currentUser { get; set; }
}
BaseController:
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
UserRepository userRep = new UserRepository();
BaseViewModel model = new BaseViewModel
{
currentUser = userRep.getCurrentUser()
};
base.OnActionExecuted(filterContext);
}
}
HomeController: (default)
public class HomeController : BaseController
{
public ActionResult Index()
{
ListRepository listRep = new ListRepository();
return View(listRep.GetAllLists());//returns IEnumerable<ListModel>
}
}
My shared _layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Public/css")
</head>
<body>
<header>
#Html.Partial("_Header")
</header>
#RenderBody()
</body>
</html>
and finally, my _Header.cshtml:
<div id="logo">
<h1>Hello #Model.currentUser.username</ h1 >
</div>
But I get this error message when I run it:
'System.Collections.Generic.List' does not contain a definition for 'currentUser'
I thought my BaseViewModel would always get appended
The model in the view is IEnumerable<ListModel> and that is what will be passed to the partial unless you specify a model, for example, using
#Html.Partial("_Header", someOtherModel)
Instead, create a ChildActionOnly method that returns your user data to the _Header.cshtml partial view and in the main view use #Html.Action() to render it
[ChildActionOnly]
public ActionResult _Header()
{
var model = .... // get the model you want to render in the partial
return PartialView(model);
}
and in the main view
#{ Html.RenderAction("_Header", controllerName); }
If you want that in every view, you may consider calling a child action method using Html.Action.
So replace
<header>#Html.Partial("_Header")</header>
with
<header>#Html.Action("Header","YourControllerName")</header>
Now have an action method called Header where you will pass the needed data to it's partial view
[ChildActionOnly]
public ActionResult Header()
{
var vm = new YourHeaderViewModel();
vm.UserName="Shyju"; // Replace with whatever you want.
return PartialView(vm);
}
Where YourHeaderViewModel is your view mode for the header with the properties needed for the header.
public class YourHeaderViewModel
{
public string UserName {set;get;}
}
Now in your Header partial view which is strongly typed to the YourHeaderViewModel class,
#model YourHeaderViewModel
<div id="logo">
<h1>Hello #Model.UserName</ h1 >
</div>
Another possible solution using BaseController.
Instantiate your BaseViewModel model in OnResultExecuting method instead of OnActionExecuted. And save the model in ViewData to access it in _Header partial view.
E.g.
public class BaseController : Controller
{
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
UserRepository userRep = new UserRepository();
BaseViewModel model = new BaseViewModel
{
currentUser = userRep.getCurrentUser()
};
filterContext.Controller.ViewData["customData"] = model;
}
}
Now you need to pass ViewData to _Header partial view.
E.g.
#Html.Partial("_Header", ViewData["customData"])
In _Header partial view, you can simply access the data.
<div id="logo">
<h1>Hello #Model.currentUser.username</ h1 >
</div>

CS 1061 error on ASP.Net

im just start learning asp.net and encounter this error
i've tried many solution from google but still get this error (errr...)
Compiler Error Message: CS1061: 'Exercise1.Visitor' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'Exercise1.Visitor' could be found (are you missing a using directive or an assembly reference?)
im using VS2012 with 4.5 Net
this is my code
Model
namespace Exercise1.Models
{
public class Visitor
{
public String Name
{
set;
get;
}
}
}
Controller
namespace Exercise1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Visitor data)
{
ViewBag.Message= "Hi my name is" + data.Name;
return View();
}
}
}
View
#{
Layout = null;
}
#model Exercise1.Visitor
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>
#using(Html.BeginForm())
{
<p>
#Html.LabelFor(m=>m.Name);
</p>
}
</div>
</body>
</html>
btw, this is my first question hehe
Change model to:
#using Exercise1.Models
#model Exercise1.Models.Visitor
Do you have another Vistor class in your project? it's saying Exercise1.Visitor when it should be complaining about Exercise1.Models.Visitor
make sure you're referencing Exercise1.Models.Visitor

Spring / Resource handler location

I have common problem in spring with resource locator and can not figure out where is problem (CSS style is not working:
My .JSP page and HTML code :
<head>
<link href="/css/basicStyle.css" rel="stylesheet" type="text/css"/>
</head>
My resource locator configuration :
#Configuration
#ComponentScan("loginsystem.controllers")
#EnableWebMvc
public class ServletConfig extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver =
new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
resolver.setViewClass(
org.springframework.web.servlet.view.JstlView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/css/**").addResourceLocations("/LoginSystem/WebContent/WEB-INF/css/");
}
}
SOLUTION :
After looking in other questions I have found solution :
<link href="${pageContext.request.contextPath}/css/basicStyle.css/" rel="stylesheet" type="text/css"/>
Can any one explain why pageContext is needed ?
Change the resources locations from "/LoginSystem/WebContent/WEB-INF/css/" to "/WEB-INF/css/"
There's a dedicated JSP tag for this:
<!doctype html>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<link href="<spring:url value="/css/basicStyle.css"/>"
rel="stylesheet" type="text/css"/>
If you want to have better resource handling support in your application, you may also want to register a ResourceUrlEncodingFilter in your application.

Resources