Want to hyperlink to a controller method not a view - c#

I want the Logout link to carry out a process located in HomeController and not to display a new View. How do I go about structuring this?
Controller method:
public ActionResult LogoutProcess()
{
previousLoggedIn = WebSecurity.CurrentUserName;
WebSecurity.Logout();
return RedirectToAction("Logout", "Home");
}
public ActionResult Logout(HomeModels.LogoutModel model)
{
model.PreviouslyLoggedInUsername = previousLoggedIn;
return View(model);
}
View:
Logout

You can use the standard link, targeting that action
#Url.Action("LogoutProcess", "Home")
The "trick" is in Redirection to some other View at the end of your LogoutProcess() action:
public ActionResult LogoutProcess()
{
// TempData to transfer user name
TempData["previousLoggedIn"] = WebSecurity.CurrentUserName;
WebSecurity.Logout();
return RedirectToAction("Logout", "Home");
}
public ActionResult Logout(HomeModels.LogoutModel model)
{
// fill model from TempData
model.PreviouslyLoggedInUsername = TempData["previousLoggedIn"];
return View(model);
}
The CurrentUserName is passed to other action via TempData

Try this:
public ActionResult LogoutProcess()
{
WebSecurity.Logout();
//return null;
Return RedirectToAction("Index");//or whatever page you want to display after logout.
}

Have you considered a no content http status code result?
return new HttpStatusCodeResult(HttpStatusCode.NoContent);

Related

Get Id from new record in ASP.NET Core MVC

I have the following action methods in my controller:
// GET: MenuOrders/Create
public IActionResult Create()
{
ViewData["MasterMenuId"] = new SelectList(_context.MasterMenu, "MasterMenuId", "MasterMenuId");
return View();
}
// POST: MenuOrders/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("MenuOrderId,CustomerName,MasterMenuId,OrderQty,IsPaid,IsCancel")] MenuOrder menuOrder)
{
if (ModelState.IsValid)
{
_context.Add(menuOrder);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["MasterMenuId"] = new SelectList(_context.MasterMenu, "MasterMenuId", "MasterMenuId", menuOrder.MasterMenuId);
return View(menuOrder);
}
After I execute it, it will redirect to the Index page. I want to change it, so it will stay on the same view with the same data, including the Id (retrieved).
My question is: how can I do that?
Thank you
I want to change it, so it will stay on the same view with the same
data, including the Id (retrieved).
Well, you can do that in following way:
Controller:
Instead of this return RedirectToAction(nameof(Index)); You have to return to create view page and menuOrder.MenuOrderId will return us last inserted id. So the code would be as :
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("MenuOrderId,CustomerName,MasterMenuId,OrderQty,IsPaid,IsCancel")] MenuOrder menuOrder)
{
if (ModelState.IsValid)
{
_context.Add(menuOrder);
await _context.SaveChangesAsync();
int lastInsertedId = menuOrder.MenuOrderId;
ViewBag.lastensertedId = lastInsertedId ;
return View("Create") ;
}
ViewData["MasterMenuId"] = new SelectList(_context.MasterMenu, "MasterMenuId", "MasterMenuId", menuOrder.MasterMenuId);
return View(menuOrder);
}
Note: if you want to clear the existing form in that case you can use ModelState.Clear(); before return View("Create"). I have just provide you the last Inserted Id demo by binding in viewbag you can even bind that in your model as well.
View:
In view you could set:
Output:

Redirect from controller to another view of another controller

I have two controllers Home and BookReservation , i am trying to redirect from BookReservation controller to view of Home controller without redirect to index of home controller if possible .
this is my action on BookReservation controller :
Validate_rules function return List<string[]> and store them in tempdata
[HttpPost]
public ActionResult Validate_Data(ReservationDetails reservation_details)
{
TempData["verification_errors"] = Validate_rules(reservation_details);//this function return List<string[]>
return RedirectToAction("Index");
}
and here the view index.cshtml of home i get the temp data and display the elements of it:
#{
List<string[]> validate_rules = new List<string[]>();
if (TempData["verification_errors"] != null)
{
validate_rules = (List<string[]>)TempData["verification_errors"];
}
}
#foreach (var item in validate_rules)
{
<label >#item[0].ToString() #item[2].ToString()</label>
}
the problem is i can not display the validate_rules elements inside view label i don't know where the problem from when i redirect the temp-data from BookReservation controller or what ?
this is home controller :
[HttpGet]
[ActionName("Index")]
[HandleError]
public ActionResult Index_Get(string submit)
{
bool ParamsChanged = mySessionObject.Parameters.LoadQueryParameters(Request);
if (ParamsChanged)
return RedirectToAction("Index", mySessionObject.Parameters.GetQueryParameters());
LoadHotelDetails();
GetHotelAvailability();
ViewBag.data = TempData["verification_errors"];
return View("Index",myViewModel);
}
any advice ?
change this return RedirectToAction("Index");
to return RedirectToAction("Index","Home"); in Book Reservation controller
Book Reservation Controller
-
[HttpPost]
public ActionResult Validate_Data(ReservationDetails reservation_details)
{
TempData["verification_errors"] = Validate_rules(reservation_details);//this function return List<string[]>
return RedirectToAction("Index", "Home");
}
-- Home Controller
public ActionResult Index()
{
ViewBag.data= TempData["verification_errors"];
}
-- View
if (ViewBag.data!= null)
{
var list = ViewBag.data;
foreach (var item in list)
{
<label >#item[0].ToString() #item[2].ToString()</label>
}
}
Looks like the problem is a composite one and it requires some decomposition:
A controller redirects to an action, so it definitely should be:
return RedirectToAction ("YourAnotherAction", "YourAnotherController");
I cannot find the action of the Home Controller you are trying to redirect to. You want to avoid Index action of your Home Controller, but do not define the exact action you want to view.
Try to send some other data and check if all your routs are OK. Just check if you are examining the same area, project etc.
Just check if TempData is empty.
At last, Ashkan Mobayen Khiabani provided a good suggestion, check it. What's the problem that still persists? He proposes to redirect to some other action - try it.
Hope that helps.
You can tell which view to load by using its path:
public ActionResult BookReservation()
{
return View("Home/Index");
}
You can even do something like this:
public ActionResult SomeAction()
{
if(SomeValue)
return View();
else
return View("Errors/AccessDenied");
}
TempData only retains information for two subsequent requests & often used for passing data between controllers (redirect). You can use ViewBag to pass the values into view:
Controller
public ActionResult Validate_Data(ReservationDetails reservation_details)
{
TempData["verification_errors"] = Validate_rules(reservation_details);//this function return List<string[]>
return RedirectToAction("Index");
}
public ActionResult Index()
{
var verification_errors = TempData["verification_errors"];
ViewBag.Errors = verification_errors;
// do something
return View();
}
View
#{
List<string[]> validate_rules = new List<string[]>();
if (ViewBag.Errors != null)
{
validate_rules = (List<string[]>)ViewBag.Errors;
}
}
#foreach (var item in validate_rules)
{
<label>#item[0].ToString() #item[2].ToString()</label>
}
Or simply use TempData.Keep to keep the contents before returning view:
public ActionResult Index()
{
TempData.Keep("verification_errors");
// do something
return View();
}
References:
TempData value not persisting if used in view
Losing data from viewbag/tempdata after multiple post

How to pass tempdata in RedirectToAction in ASP.Net MVC

I need to pass one logout successful message in one of the views but I am not able to do so. Here is what I have.
Not Working Solution:
//LogController:
public ActionResult Logoff()
{
DoLogOff();
TempData["Message"] = "Success";
return RedirectToAction("Index", "Home");
}
// HomeController
public ActionResult Index()
{
return View();
}
Index CSHTML File:
#Html.Partial("../Home/DisplayPreview")
DisplayPreview CSHTML File:
#TempData["Message"]
Working Solution
public ActionResult Logoff()
{
DoLogOff();
return RedirectToAction("Index", "Home", new { message = "Logout Successful!" });
}
public ActionResult Index(string message)
{
if (!string.IsNullOrEmpty(message))
TempData["Message"] = message;
return View();
}
Index CSHTML File:
#TempData["Message"]
But I want something like my first solution.
In the controller;
public ActionResult Index()
{
ViewBag.Message = TempData["Message"];
return View();
}
public ActionResult Logoff()
{
DoLogOff();
TempData["Message"] = "Success";
return RedirectToAction("Index", "Home");
}
Then you can use it in view like;
#ViewBag.Message
See if this works:
public ActionResult Logoff()
{
DoLogOff();
ControllerContext.Controller.TempData["Message"] = "Success";
return RedirectToAction("Index", "Home");
}
Since you don't show what DoLogOff() does, my guess is that you are abandoning the session, which means any data stored in session (like TempData) is lost. A new session does not get generated until the next page refresh, so it doesn't work.
What you might try is simply passing a flag to your Index view that will show the logged off message if it's present. I would NOT use the string message, like you show in your "working" example, because this can be coopted by attackers to redirect people to malicious sites.
hi i want to share my version
public ActionResult List(string success,string error)
{
TempData["success"] = success;
TempData["error"] = error;
return View();
}
public ActionResult Add()
{
return RedirectToAction("List",new
{
error = "not added",
success = "added"
});
}

#ViewBag getting null value from UserProfile

i'm having some problems with to pass value from UserProfile to #Viewbag to show in Index.cshtml.
Let's explain:
When i'm do a Register of new user or Login, i'm trying to pass UserType field from UserProfile in a viewbag.
UserType is a custom field that i create on UserProfile to validate if the user is a "Musico" or "Ouvinte"
After debug application, I see that viewbag is taking NULL value.
This is the code that i try to get value from UserProfile in Register and Login post method:
LOGIN POST METHOD
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName,
model.Password,
persistCookie: model.RememberMe))
{
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
var userType = user.UserType;
TempData["UserType"] = userType; //Taking UserType from User Profile
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
REGISTER POST METHOD
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
var context = new UsersContext();
var username = User.Identity.Name;
var user = context.UserProfiles
.SingleOrDefault(u => u.UserName == username);
var userType = user.UserType;
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new
{
UserType = model.UserType
});
WebSecurity.Login(model.UserName, model.Password);
// string currentUserType = u.UserType;
TempData["UserType"] = userType;//Get the userType to validate on _Layout
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
return View(model);
}
Calling viewbag in part of Index page
<p>
#if (Request.IsAuthenticated && ViewBag.UserType.Equals("Musico"))
{
<span>musico</span>
}
else if (Request.IsAuthenticated && ViewBag.UserType.Equals("Ouvinte"))
{
<span>ouvinte</span>
} else{
<span>teste</span>
}
</p>
HomeController
public ActionResult Index()
{
ViewBag.UserType = TempData["UserType"];
return View();
}
See this article for a good explanation, When to use ViewBag, ViewData, or TempData.
.. once the controller redirects, the ViewBag and ViewData will contain null values. If you inspect the TempData object with debugging tools after the redirect you'll see that it is fully populated.
Do this instead:
TempData["UserType"] = userType;
Change your view accordingly i.e.
#{var tempUserType = TempData["UserType"]} // in the top
And then use it as you would with the ViewBag
The ViewBag is lost because of the redirect.
An easy solution would be to use TempData, which only remains valid after one extra request. After that, it is normally gone, there is however a Keep method.
From MSDN:
However, the data in a TempDataDictionary object persists only from
one request to the next, unless you mark one or more keys for
retention by using the Keep method. If a key is marked for retention,
the key is retained for the next request.
Example:
[Authorize]
public class AccountController : Controller
{
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// do stuff
TempData["UserType"] = userType;
return RedirectToAction("Index", "Home");
}
// something went wrong, return view
return View(model);
}
}
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.UserType = TempData["UserType"];
return View();
}
}

how can I re-direct to different pages using the same controller ActionResult?

I have two views using the same ActionResult. There was originally only one view but now there is the need for a second.
The views are - "Index" & "Accepted"
Index
[HttpGet]
public ActionResult Index(string status, string message)
{
var InboxStatus = InboxStatus.New;
if (!Enum.TryParse(status, out inboxStatus))
inboxStatus = InboxStatus.New;
var model = new InboxModel();
model.Status = inboxStatus.ToString();
model.InboxMailCount = GetInboxMailCount();
model.InboxMailCount.Status = InboxStatus.ToString();
#ViewBag.Message = message;
return View(model);
}
Accept
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Accept(InboxModel model)
{
if (ModelState.IsValid)
{
var inboxmail = _repo.GetById(model.ID);
inboxmail.Status = (int)ReferralStatus.Accepted;
inboxmail.AcceptedByUserId = UserId;
inboxmail.AcceptenceDateTime = DateTime.Now;
_uow.SaveChanges();
return RedirectToAction("Index", new { Message = "Accepted Successfully" });
}
return View(model.ID.ToString());
}
The ActionResult is called "Declined",
The problem is that the Action Result contains the following...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Decline(InboxModel model)
{
if (ModelState.IsValid)
{
var InBox = _repo.GetById(model.ID);
InBox.Status = (int)ReferralStatus.Declined;
InBox.DeclinedByUserId = UserId;
InBox.DeclinedDateTime = DateTime.Now;
_uow.SaveChanges();
return RedirectToAction("Index", new { Message = "Declined Successfully" });
}
return Accept(model.ID.ToString());
}
So if the user select's the "Declined" action on either page they will be re-directed to "Index" regardless of them carrying out the action on the "Accepted" view.
Make sense,? I want to re-direct them back to the page they came from.
Please note this is how I am currently re-directing to "Accepted" for different action...
As the lists in Index depend on the "Status" property...
Index view..
ASP.Net MVC 4 using razor 2 views.....any ideas?
You can use something like ViewBag.ReturnUrl to store the most recent ActionName in the sequence of operations.
Example:
public ActionResult ActionA(){
ViewBag.ReturnUrl = "ActionA";
return View();
}
public ActionResult ActionB(){
ViewBag.ReturnUrl = "ActionB";
return View();
}
public ActionResult Declined(){
return RedirectToAction(ViewBag.ReturnUrl);
}
You can try to cache or save your previous url and then just redirect back to it.
public ActionResult Index()
{
var previousPage = System.Web.HttpContext.Current.Request.UrlReferrer;
//Yourlogic
RedirectToAction(previousPage);
}
Just add a property in your InboxModel to state your origin.
Then, in your forms you can place a Hidden with that value.
BTW, you are redirecting to Index without passing the Status parameter... am I wrong?
Got it !! Apologies, it was not a straight forward question as there was alot of code to add to the confusion, thanks to all for you time..
Basically save the initial status of the mail at the begining of the action..
As it the status only changes within the action.
At the top of the Accepted ActionResult,
var returnStatus = Mail.Status;
Then use that variable in the return....
return RedirectToAction("Index", new { Status = (int)returnStatus, Message = "Mail Successfully added to Sent Listing" });

Categories