How to get a url after returning the view? - asp.net-mvc-4

I am new to MVC4, I am using more then one form in one View. When i am posting the form i am getting all the formcollecion values in controller. When i am returning the different view also, its working fine. My problem is after returning view, the url showing that post method name.when i try to refresh this page its showing error.
Initially the url was : Admin/Activities
after posting the form : Admin/UpdateActivity
I need url like this after returning the view : Admin/Activities
how to get it, Please help me. Thanks in advance.
I dont have any separate view for this ActionResult. This is my code:
[HttpPost]
public ActionResult UpdateActivity(FormCollection coll)
{
................
ViewBag.updateAlert = "Activity updated sucessfully";
return View("Activities");
}

#using (Html.BeginForm("UpdateActivity", "Admin", FormMethod.Post,new { #id = "formID" }))
Change your form attribute as it. It will automatically return to the view Activities.
Note: if your form on Admin/Activities.

After updating the record,you can Redirect to that action,instead of returning the same view again, and instead of ViewBag you will have to use TempData as ViewBag will be null after redirecting:
[HttpPost]
public ActionResult UpdateActivity(FormCollection coll)
{
................
TempData["updateAlert"] = "Activity updated sucessfully";
return RedirectToAction("Activities","Admin");
}

Related

MVC 4 website back press return the same form with old values

I am new in MVC 4 web development and i am creating a control panel. I have developed a Add user page and submit information in database successfully.
But after submit when i press back button it will show previous form.
i am using redirection the page to same page after submit form.
here is the code to redirect
public ActionResult AdminPanel(RegisterUserModel user)
{
if (ModelState.IsValid) // Check the model state for any validation errors
{
if (user.AddUserToDB(user.username, user.password, user.fullName,user.contactNo,user.COAId)) // Calls the Login class checkUser() for existence of the user in the database.
{
TempData["SuccessMessage"] = "User Added Sucessfully!";
ModelState.Clear();
return Redirect("AdminPanel");
}
else
{
ViewBag.SuccessMessage = "User Not Added";
return View();
}
}
SelectList clientsList = GetClinetList();
ViewBag.clientsList = clientsList;
return View(); // Return the same view with validation errors.
}
I have tried many examples but issue not resolved yet so kindly give my suggesstions
If you don't want the user to be able to see the previous content when clicking back, then you must indicate that content should not be cached by the browser and must revalidate with the origin server
A summary of this behaviour is here - http://blog.55minutes.com/2011/10/how-to-defeat-the-browser-back-button-cache/
You could create a nocache attribute, like this one - https://stackoverflow.com/a/10011896/1538039, and apply it to your controller methods.

Post back Errors in MVC 4

In regular Asp.Net, when you want to post an error, for ex, a duplicate ID, I use Panels for controls, error message labels, etc. I was wondering, how to achieve the same using MVC 4.
Currently, on my Index page, I have an Id, Name & Address column and a Submit button. My HTTPPOST ActionResult here:
[HttpPost]
public ActionResult Index(Person p)
{
if (ModelState.IsValid)
{
PersonInfo pi = new PersonInfo();
var duplicate = from d in db.PersonInfoes
where d.Id == p.Id
select d;
if (duplicate.Any())
{
return View("Duplicate");
}
else
{....}
When I enter a duplicate Id, upon submitting the page, I need to post to the same view ("Index") page to let user know that there is an Id already, but currently, I am redirecting to a different view to let user know as a duplicate, and I dont think this is the right way to do this. I am learning MVC, btw and hence this doubt. My duplicate cshtml here:
#{
ViewBag.Title = "Duplicate";
}
<h2>Duplicate</h2>
<h3>Duplicate ID found !!</h3>
<p>Please correct the ID and re-enter !</p>
<br/><br/>
#Html.ActionLink("Back to Data Entry","Index")
Any pointers would help.
You can return to the same view. You should consider adding an error to the model state dictionary so that you can show that in the UI.
[HttpPost]
public ActionResult Index(Person p)
{
if (ModelState.IsValid)
{
var duplicate= db.PersonInfoes.Where(s=>s.Id== p.Id);
if (duplicate.Any())
{
ModelState.AddModelError(string.Empty,"Duplicate found");
return View(p);
}
// to do : Your existing code
}
return View(p);
}
Just make sure you are calling the ValidationSummary method in your Index view to show this error message.
#model Person
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
<!-- Your form fields goes here-->
<input type="submit" />
}

What ActionResult should you return to update just the ActionLink text?

I'm using MVC4 with Entity Framework and like many people I'm new to MVC and trying to get my head around the design patterns.
I have a partial view that displays a list of sessions followed by actionlinks allowing the authenticated member to book into the sessions.
Note: for clarity, I've chopped out most of the code, if a member is booked into a session, it displays "Booked" instead of the action link.
#using OnlineBookings.Website.Models
#{ DateTime currentDate = DateTime.MinValue.Date; }
<form method="post" action="~/Controllers/BookSessionController.cs">
#foreach (SessionsWithBookingInformation s in Model)
{
<p>#s.StartTime.ToString("t")
#s.Description
#Html.ActionLink(
"Book",
"BookSession",
new { sessionId = s.SessionId }
)
</p>
}
</form>
This then displays as part of a larger view:
The actionlinks pass the guid of the session to be booked through to the following function in my controller, which retrieves the memberId from the cookie and uses Entity Framework to create a booking for that member and session.
public ActionResult BookSession(Guid sessionId)
{
using (var db = new OnlineBookingsEntities())
{
// see if the member id is stored in a cookie
if (Request.Cookies["memberId"] != null)
{
var memberId = new Guid(Request.Cookies["memberId"].Value);
db.Bookings.Add(new Booking
{
BookingId = Guid.NewGuid(),
MemberId = memberId,
SessionId = sessionId,
BookingTime = DateTime.Now
});
db.SaveChanges();
}
}
// this refreshes the entire page
/// is there a better way to just replace the actionlink they clicked on?
return RedirectToAction("Index", "Home");
}
All this is working nicely and bookings are being effectively recorded.
But, I'm trying to figure is if the return from the BookSession function can just update the actionlink text.
Ideally, on success, I want to replace the ActionLink in my partial view with the word "Booked" and on failure I want to replace it with the failure condition like "Session full".
Or I could just update my partial view, because that will do the same thing.
Am I missing something simple here? Or, am I barking up entirely the wrong tree?
Your question is great and really well explained, but it's also a little vague since it's a bit of a "What should I do?" question. Here are a few options that might help you develop a solution.
Redisplay the same view. Return whichever view the user was on for them to submit the link. This will look like a simple refresh.
return View();
Submit the request via AJAX and update via a partial view. Put an id tag on a span or similar HTML element with an individual booking's details inside. Submit the request with AJAX, perhaps via #Ajax.ActionLink, and have your action return a partial view.
return PartialView("_OnlineBookingPartial", model);
Once your partial view is returned, update the specific booking with the data returned.
Use AJAX again, but return JSON. Another way might be that you use AJAX again but instead you return JSON and do something with it. You could, for example, return text in which you would replace Book with; i.e. "Session full" or "Booked!".
return new JsonResult
{
Data = "Booked!"
}
Personally, I'd probably use AJAX to update with a non-AJAX (non-Javascript) fallback.
You can do this by using #Ajax.ActionLink and checking if the request is AJAX or not inside your controller action.
if (Request.IsAjaxRequest) {
return PartialView("_OnlineBookingPartial", model);
}
return View();
This means that if the browser has Javascript enabled and supports AJAX, it will be used and the whole process will be seamless and instant for the user. If Javascript is disabled, the page will simply refresh.

How to avoid rendering entire page when using CGridView via AJAX

When creating any ajax request in yii CGridView like (pagination, filtering, ...etc) the result of request will render whole page, how can i avoid that?
I tried to use renderPartial for view but it doesn't work. if this is the solution, how can i do it?
I just need to render the table of GridView not whole page.
Please advice.
In controller:
$this->layout = false;
For me works also $this->renderPartial() in controller instead of $this->render()
if(Yii::app()->request->isAjaxRequest()) $this->renderPartial('view');
else $this->render('view');
U can create class:
class Controller extends CController {
public function beforeAction($action) {
if(Yii::app()->request->isAjaxRequest) $this->layout = false;
return parent::beforeAction($action);
}
}

Generating a modal jQuery partial view with MVC4 does not work

I like the way MVC4 manage the new logon screen: it is possible to have a modal dialog showed.
I tried to reproduce the same behavior in the same solution for another view. But it doesn't work because Request.QueryString["content"] is null. I don't know why. In fact, there is an action method called ContextDependentView (generated by the MVC template) where the trick occurred. Here it is:
private ActionResult ContextDependentView()
{
string actionName = ControllerContext.RouteData.GetRequiredString("action");
if (Request.QueryString["content"] != null)
{
ViewBag.FormAction = "Json" + actionName;
return PartialView();
}
else
{
ViewBag.FormAction = actionName;
return View();
}
}
If the value of Request.QueryString["content"] is not null then we display a partial view (modal jQuery) otherwise it is a classic view.
Can someone help me understand why this is not working?
PS: another thread already exists but without any solution.
The login and register links are bound to a click handler in AjaxLogin.js which then adds content=1 in loadAndShowDialog