i am working with spring mvc framework. i have two submit buttons on a page. that are forwarding request to two different controller. how can i use two action on single jsp page .
please suggest.
my controller are as
1.
#RequestMapping(value = "/user/reset", method = RequestMethod.POST)
public String editUser(#ModelAttribute("users") User user,
BindingResult result) {
Integer uid=user.getId();
User resetUser = usersService.findUser(uid);
resetUser.setActive(0);
ResetPasswordLog resetPasswordLog=new ResetPasswordLog();
usersService.addUsers(resetUser);
resetPasswordLogService.setTempHash(uid);
String TEMPHASH= resetPasswordLog.getTempHash();
System.out.println("www.lacas.com/reset?uid="+uid+"&th="+TEMPHASH);
return "redirect:/secure/user/" + uid;
}
2.
#RequestMapping(value = "/user/edit", method = RequestMethod.POST)
public String addUser(#ModelAttribute("users") UserForm userForm,
BindingResult result) {
Map<String, String> map = new LinkedHashMap<String, String>();
User user = usersService.findUser(userForm.getId());
Integer userId = userForm.getId();
User newUser = usersService.findUser(userForm.getEmail());
user.setName(userForm.getName());
if (newUser == null) {
user.setEmail(userForm.getEmail());
user.getRoles().clear();
Integer[] roleIds = userForm.getRoleIds();
for (Integer roleId : roleIds) {
if (roleId != 0) {
Role role = roleService.findRole(roleId);
user.getRoles().add(role);
}
}
usersService.addUsers(user);
return "redirect:/secure/users/index";
} else {
edit_exist_user = true;
return "redirect:/secure/user/" + userId;
}
}
You can by using JavaScript, and changing form's action attribute dynamically. If this is your form:
<form id="myform" action="#" onsubmit="return pickDestination();">
<input type="submit" name="sbmitbtn" value="edit" onclick="document.pressed=this.value"/>
<input type="submit" name="sbmitbtn" value="reset" onclick="document.pressed=this.value"/>
</form>
Then your pickDestination JS function would look like:
function pickDestination()
{
var a = "/user/" + document.pressed;
document.getElementById("myform").action = a;
return true;
}
I'm going to preface this by saying that I'm not very familiar with spring applications, however in many other java based MVC systems I've accomplished this by simply giving my submit buttons a name and parsing off this in the action class by checking the request.
For example find which submit button was used by it's parameter name, call the appropriate methods. The following is an example of a struts based solution I use on occasion. If you can access the servlet request object in your spring controller, you could do something similar.
#Override
public String execute() throws Exception {
try {
// Check the request for a someone clicking the logout submit button
if (found("logout")) {
user.logout(); //invoke the logout method
session.remove("user");
return SUCCESS;
}
// Check the request for a someone clicking the login submit button
if (found("login")) {
user.login();
session.put("user", user);
return "login";
}
// Catch any login exceptions
} catch (Exception e) {
user = null;
addActionError(e.getMessage());
return INPUT;
}
return SUCCESS;
}
// The following method checks for a request paramater based on the key (String)
// provided. If the key is not found or the value for the parameters is empty, it
// returns false;
private boolean found(String param) {
Object temp = request.getParameter(param);
if (temp != null) {
if (temp.toString().isEmpty()) {
return false;
}
return true;
} else {
return false;
}
}
Related
A AuthorizedAttribute named as JwtAuthenticateAttribute is implemented and did something
It can be triggered for each request of the below API
[HttpGet]
[JwtAuthenticate]
public GetFaqListDS Index([FromUri] GetFaqListModel model)
{
List<MP_faqs> res = Faq.GetFaqList(model.curPage, model.pageSize);
var re = Request;
var hds = re.Headers;
GetFaqListDS ds = new GetFaqListDS();
ds.data = res;
return ds;
}
The question is, how to pass a value to this controller's function from the Attribute JwtAuthenticate.
P.S the value exists at the OnAuthorization of this attribute.
Thanks.
Add the required value in "actionContext.Request.Properties" in Onauthorize method and access these in controller.
Adding UserDetail Model :
actionContext.Request.Properties.Add("__user", new UserDetails(){userid=123, username="ABC"});
Retrieving values :
private static UserDetails GetUserDetailsFromRequest()
{
object tempVal;
try
{
var httpRequestMessage = (HttpRequestMessage)HttpContext.Current.Items["MS_HttpRequestMessage"];
httpRequestMessage.Properties.TryGetValue("__user", out tempVal);
if (tempVal == null) return null;
var user = (UserDetails)tempVal;
return user;
}
catch
{
}
return new UserDetails();
}
Hope this will helps you.
i am using thymeleaf in spring boot and reading the session attributes like this on the index page
<p th:text="${session.counter}" th:unless="${session == null}">[...]</p>
where the counter is coming from the below function
#RequestMapping({"/"})
String index(HttpSessbelow request ion session) {
session.setAttribute("counter", "0");
return "index";
}
Whenever someone click on the button on page , we should be able to increase the counter and call a url in the application , how can we achieve this
<button onclick="/activate}">...</button>
#RequestMapping({"/"})
String activate(HttpSession session) {
if(session.getAttribute(counter) == 1){
activate();
return "thanksPage" ;
}
}
Here's how I would structure it.
#RequestMapping("/")
public String start(HttpSession session) {
session.setAttribute("counter", 0);
return "redirect:/current";
}
#RequestMapping("/current")
public String current() {
int counter = (Integer) session.getAttribute("counter);
if (counter == 1) {
activate();
return "thanksPage";
} else {
return "index";
}
}
#RequestMapping("/increment")
public string increment(HttpSession session) {
session.setAttribute("counter", ((Integer) session.getAttribute("counter)) + 1);
return "redirect:/current";
}
And the button should go to /increment
<button onclick="/increment">...</button>
I have a page with many items on it. Each one has a button, that is supposed to take user to another jsp with another layout for detailed information about the current item. Can I even do this with ResponseEntity, as it doesn't redirect anywhere? Or may be there's some better way to do it and send my Object to the page? I tried "ResponseEntity.created(location).body(object)" but it doesn't do the job, I stay on the same page. May be I'm just using it wrong?
My method:
#RequestMapping(value = {"/details+{id}"}, method = RequestMethod.GET)
public ResponseEntity<Item> details(#PathVariable("id") int id) {
Item item = itemService.findById(id);
if(item == null){
return new ResponseEntity<Item>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<Item>(item, HttpStatus.OK);
}
Have a look at ModelAndView. It's purpose is to return a view with attached model to it. So for each value of the id, you can decide a pair of view and model to return.
#RequestMapping(value = {"/details+{id}"}, method = RequestMethod.GET)
public ModelAndView details(#PathVariable("id") int id) {
String viewToUse;
Map<String, Item> modelToUse;
if(id == ...) {
viewToUse = ...
modelToUse = ...
} else if (id == ...) {
viewToUse = ...
modelToUse = ...
} else if (id == ...) {
viewToUse = ...
modelToUse = ...
}
return new ModelAndView(viewToUse, modelToUse);
}
I have two controllers, AdminController and AccountController with the following code
AccountController:
[HttpPost]
public ActionResult LogOn(LogOnViewModel model)
{
if (ModelState.IsValid)
{
_authenticationService.SetPrincipal(model.UserName);
var exists = _authenticationService.ValidateCredentials(userName, password);
FormsAuthentication.SetAuthCookie(model.UserName, false);
if(exists){
return RedirectToAction("Index", "Admin");
}
}
return RedirectToAction("LogOn");
}
AdminController:
[Authenticate]
public class AdminController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
AuthenticateAttribute is inherited from AuthorizeAttribute and has the following code:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authenticated = false;
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
{
//some actions
}
else
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
return authenticated;
}
_authenticationService is the instance of AuthenticationService class and SetPrincipal() method has the following code:
public void SetPrincipal(string userName)
{
var identity = new GenericIdentity(userName);
var principal = new GenericPrincipal(identity, null);
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
var ticket = new FormsAuthenticationTicket(1,
principal.Identity.Name,
DateTime.Now,
DateTime.Now.AddMinutes(30),
false,
String.Empty,
FormsAuthentication.FormsCookiePath);
string encryptedCookie = FormsAuthentication.Encrypt(ticket);
var authenticationCookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
if (authenticationCookie != null)
{
authenticationCookie.Value = encryptedCookie;
authenticationCookie.Expires = DateTime.Now.AddMinutes(30);
}
HttpContext.Current.User = principal;
}
}
When I debug and watch AuthenticationService.SetPrincipal() HttpContext.Current.User.Identity.IsAuthenticated is true. But after redirect to Index action of AdminController in AuthenticateAttribute.AuthorizeAttribute() HttpContext.Current.User.Identity.IsAuthenticated is always false. As result I redirected to LogOn view again.
What am I doing wrong?
I don't see anywhere where you actually send the cookie back to the client. In order to be authenticated on each subsequent request, you have to send the encrypted cookie back to the client so that it can pass it back to your site.
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
Response.Cookies.Add(cookie);
I see where you try and get the current authentication cookie here:
var authenticationCookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
But again, this is a GET, not a SET (or sending the cookie back) function line. At this point in your authentication, if you set a debugger, authenticationCookie is always going to be NULL.
Also, I don't see where you validate the password in any of your actions or functions. Ensure you are not overlooking that step.
One more thought/question/issue with your code. You are setting a variable called userExists in your controller action, but the function you call is a void type, so...you don't need to set that variable, just call the function.
_authenticationService.SetPrincipal(model.UserName);
return RedirectToAction("Index", "Admin");
I have register form. I want to check new username that is in db or not and if there is in DB , exception show next to it's textbox "UserName already exist...", what should I do?
this my method with exception that I have used it in Register action.:
public void InsertNewUser(MemberRegisterModel mm)
{
EShopThemeDBEntities context = new EShopThemeDBEntities(idbconnection.ConnStr);
using (context)
{
var listUsers = (from o in context.Users
select o.Username).ToList();
var a = listUsers.Count();
foreach (var item in listUsers)
{
if (mm.Username == item.ToString())
{
throw new Exception("UserName already exist...");
}
User mmr = new User();
mmr.FName = mm.FName;
mmr.LName = mm.LName;
mmr.Username = mm.Username;
mmr.Password = mm.Password;
mmr.Email = mm.Email;
mmr.Phone = mm.Phone;
mmr.Mobile = mm.Mobile;
mmr.CreateDate = DateTime.Now;
mmr.RoleId = 2;
context.AddToUsers(mmr);
context.SaveChanges();
}
}
You can set the Model error and return the model object back to view.
if(mm.Username == item.ToString())
{
ModelState.AddModelError("UserName","Username already taken";)
return View(model);
}
Also You do not need to get a list of usrs from database and do a loop to check whether the user entered user name exist or not. You can use the FirstOrDefault method to atleast one is there.
using (context)
{
var user=(from o in context.Users
where o.UserName==mm.UserName).FirstOrDefault();
if(user!=null)
{
ModelState.AddModelError("UserName","Username already taken";)
return View(model);
}
else
{
//Save new user info
}
}
Make sure you have the validation fields in your view, adjacent to the text box
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
But, Ideally, I would also do it asynchronosly with ajax to provide a rich user experience to the user. For that what you have to do is to look for the blur event of the text box and get the value of the textbox, make an ajax call to an action method which checks the availability of user name and return appropriate result.
<script type="text/javascript">
$(function(){
$("#UserName").blur(){
var userName=$(this).val();
$.getJSON("#Url.Action("Check","User")/"+userName,function(response){
if(response.status=="Available")
{
//It is available to register. May be show a green signal in UI
}
else
{
//not available. Show the message to user
$("#someMsgDIv").html("User name not available");
}
});
});
});
</script>
Now we should have an action method called Check in UserController to handle the ajax request
public ActionResult Check(string id)
{
bool isAvailable=false;
string userName=id;
//Check the user name is availabe here
if(isAvailable)
return Json(new { status="Available"},
JsonRequestBehaviour.AllowGet);
else
return Json(new { status="Not Available"},
JsonRequestBehaviour.AllowGet);
}
Note: Never do the client side approach only. Always do the server side checking no matter whether you have client side checking or not.
Shyju's answer is a thorough answer. However, based on your comments about handling the exception, here's a sample:
public void InsertNewUser(MemberRegisterModel mm)
{
// Some code...
if (userExists)
{
throw new ArgumentException("User name not available");
}
}
in your action method:
public ActionResult AddUser(MemberRegisterModel newUser)
{
try
{
var userManager = new MembersSrv();
userManager.InsertNewUser(newUser);
}
catch (ArgumentException ex)
{
if (ex.Message == "User name not available")
{
ModelState.AddModelError("UserName","Username already taken";)
return View(model);
}
}
}
Please note that the better way is to define a class which derives from Exception class (e.g. DuplicateUserNameException) and throw/catch that exception in your code. This sample code has been simplified.