Hi all I am working on this method that give how result one page cached:
[DonutOutputCache(
Options = OutputCacheOptions.NoCacheLookupForPosts,
Duration = 3600,
Location = OutputCacheLocation.Server,
VaryByParam = "*",
VaryByCustom = "SurveySession(calculationReference)")]
[AuthoriseIntermediaryInSameOrganisation("calculationReference")]
[HttpGet]
public ActionResult Details(string calculationReference)
{
.....
return View(model);
}
In this page I have a partial view (calculationNotes) with one form and I would that when I submit the form the page clear the cache and recharge the mother view (Details)
This is the action for the submit form where I am trying to clear the cache.
[HttpPost]
public ActionResult CalculationNotes(CalculationNotesViewModel model)
{
...
var cacheManager = new OutputCacheManager();
cacheManager.RemoveItem("Calculation", "Details");
return PartialView("_CalculationNotes", model);
}
But don't clean the cache I would that when I do the submit of the form the cache is rebuild so that the first actionresult Details will be recalculate.
Related
After POSTing to a server side method, I want to return the user back to the view from which he came, which was:
.../BrokerDashboard/Profile/Index
Here's the method:
[HttpPost]
public ActionResult Profile(ProfileModel Model)
{
// do stuff
return View("Index", Model);
}
There is logic in here that needs to execute after the form is posted:
public ActionResult Index(string contactid)
{
// do stuff
}
But after the post, the browser ends up here:
.../BrokerDashboard/Profile/Profile
Which means public ActionResult Index() does not get called again after the post.
I think what your looking for is RedirectToAction() It causes a redirect and will fire your Index controller method.
RedirectToAction with parameter
https://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction(v=vs.118).aspx
[HttpPost]
public ActionResult Profile(ProfileModel Model)
{
// do stuff
return RedirectToAction("Index", Model);
}
I have a small asp.net mvc application, where I have few actionlinks in my Index.html and following code in home controllder.
When user click on Edit ActionLink, it takes the control to HomerController's "Edit" acton method (which is of type httpGet). The view for that action method is Edit.cshtml. If I do some data manipulation in that EDIT view..and try to POST that data, What should I do ? Write another Edit action method (httpPost) in same HomeController? In that case my home controller will grow bigger right?
If I need to write seperate controller for this purpose, how do I transfer the control to that controller? ( I mean how do I attach my newly created Edit controller to Edit view ?)
List<StateCity> stateCityList = new List<StateCity>();
public ActionResult Index()
{
StateCity sc1 = new StateCity() { Id = 1, StateName = "Dallas", Cities = new List<string>() { "ab", "cd" } };
StateCity sc2 = new StateCity() { Id = 2, StateName = "Austin", Cities = new List<string>() { "ef", "gh" } };
stateCityList.Add(sc1);
stateCityList.Add(sc2);
return View(stateCityList);
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult Edit(int id)
{
return View();
}
As was told already, add one more action with HttpPost attribute and your ViewModel as parameter.
Your controller won't grow if you will follow SRP principle. In my opinion HomeController shouldn't have such actions like Edit. I would move them to corresponding Controller (for example ArticleController). But HomeController would have actions like Index, About.
#Html.ActionLink("Edit Article", "Edit", "Article", new { id= 587 }, new { id = "linkId" })
Take a look here for more details: https://msdn.microsoft.com/en-us/library/dd504972(v=vs.118).aspx
You can create Action for HTTP POST using attribute:
[HttpPost]
public ActionResult Edit(parameters here){}
Here is a nice example of forms in MVC
Typically for an edit you'd have two actions.
One for loading the edit page:
[HttpGet]
public ActionResult Edit(int id)
And one for submitting the form (performing the edit):
[HttpPost]
public ActionResult Edit(YourModel model)
If you're concerned that your controller methods are getting too large, consider abstracting the logic/saving code in another layer of your application.
I call an Action from a Login controller to authenticate users, once the user is authenticated I would like to call either the Cashier or the Supervisor action, depending on the user's role, and display the appropriate view.
I can break on AuthenticateUserByCard but RedirectToAction doesn't seem to be working.
I'm not sure if what I'm trying to do is deviating from the MVC architecture, if so please suggest the correct way to do this
Login controller:
public class LoginController : Controller
{
public ViewResult Index()
{
return View();
}
[HttpPost]
public ActionResult AuthenticateUserByCard(string token)
{
//Authenticate user and redirect to a specific view based on the user role
Role role = GetRoleByToken(token);
if(role.UserType == UserType.Supervisor)
return RedirectToAction("Supervisor", "Login", new { id = token });
else
return RedirectToAction("Cashier", "Login", new { id = token });
return null;
}
public ActionResult Supervisor(string id)
{
//Do some processing and display the Supervisor View
return View();
}
public ActionResult Cashier(string id)
{
//Do some processing and display the Cashier View
return View();
}
}
Java Script:
$.get("/Login/AuthenticateUserByCard",{token:token});
jQuery post and get ignore 301 browser redirects returned from the server. You would normally need to handle them yourself. This can get messy: How to manage a redirect request after a jQuery Ajax call
All you really need in this case is to return the choice of methods, but make them return explicit views (not implicit). The default would always be to return the view based on the IIS-called method i.e. "AuthenticateUserByCard" unless you specify the view.
e.g.
public class LoginController : Controller
{
public ViewResult Index()
{
return View();
}
[HttpPost]
public ActionResult AuthenticateUserByCard(string token)
{
//Authenticate user and redirect to a specific view based on the user role
Role role = GetRoleByToken(token);
if(role.UserType == UserType.Supervisor)
return Supervisor(token);
else
return Cashier(token);
return null;
}
public ActionResult Supervisor(string id)
{
//Do some processing and display the Supervisor View
return View("Supervisor");
}
public ActionResult Cashier(string id)
{
//Do some processing and display the Cashier View
return View("Cashier");
}
This will not change the URL though. If you need that too try the other answer I linked. You basically handle the redirect in jQuery and goto the new page.
Alternatively, to change the URL, put the desired URL into a hidden field of the returned views and extract that value to update the browser URL (just a thought) :)
Taking first steps with ASP.NET MVC, I am trying to create a simple (and typical) article-with-comments page: under an article itself there should be a form enabling an user to post a comment to the article.
I created a partial view for the submit form and CommentController with following methods:
public ActionResult Add(int entryId);
[HttpPost]
public ActionResult Add(Comment comment);
Then, under the article in a view of HomeController:
<div class="add-comment">
#{ Html.RenderAction("Add", "Comment", new { entryId = Model.EntryId }); }
</div>
The form renders properly and the adding procedure actually works (comment gets saved into database), but after redirecting back to the article InvalidOperationException is thrown, with Html.RenderAction (the one shown above) highlited in debugger:
System.InvalidOperationException: Child actions are not allowed to perform redirect actions.
Why does it happen?
Here's the code for CommentController methods:
public ActionResult Add(int entryId)
{
var comment = new Comment { EntryId = entryId };
return PartialView(comment);
}
[HttpPost]
public ActionResult Add(Comment comment)
{
if (ModelState.IsValid)
{
comment.Date = DateTime.Now;
var entry = db.Entries.FirstOrDefault(e => e.EntryId == comment.EntryId);
if (entry != null)
{
entry.Comments.Add(comment);
db.SaveChanges();
return RedirectToAction("Show", "Home", new { id = entry.EntryId });
}
}
return PartialView(comment);
}
Or maybe should I even take a diffrent approach?
Add HttpGet on the other Add action
You should/could be using RenderPartial instead of RenderAction:
Html.RenderPartial("YourPartialView", new Comment { EntryId = Model.EntryId });
There appears to be no need to use your action method if all you are doing is instantiating a model that you already have the ID too.
I have a ASP.NET MVC 3 app with a common scenario where there is with an "About" controller using "Contact" and "ThankYou" actions.
I want user to go to /about/contact, fill out the form, submit it, and be taken to /about/contact/thankyou * page where the form contents (aka view model) will be displayed.
** Note there is no "Contact" controller nor do I want to create one for this purpose if possible.*
I am using RedirectToAction to prevent resubmission (Post/Redirect/Get pattern) and TempData to pass on view model to thank you page.
I can also use TempData to check if thank you page was reached directly and redirect back to contact form page (so it would not register as a "goal" in web analytics)
But one thing I could not figure out is how to use different route for thank you page so it appears as /about/contact/thankyou
Am I doing this right?
Is there a better way?
Here are relevant actions in AboutController
<!-- language: c# -->
[RequireHttps]
public ActionResult Contact()
{
var viewModel = new ContactViewModel();
return View(viewModel);
}
[RequireHttps]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(ContactViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
// not sure if this is the best way or how to redirect to /contact/thankyou
TempData["viewModel"] = viewModel;
return RedirectToAction("ThankYou");
}
[RequireHttps]
public ActionResult ThankYou()
{
var viewModel = TempData["viewModel"];
// upon direct access, viewModel will be null and missing, so redirect to Contact form
if (viewModel == null)
{
return RedirectToAction("Contact");
}
return View(viewModel);
}
You could define a custom route before the default route:
routes.MapRoute(
"contact",
"about/contact/thankyou",
new { controller = "About", action = "ThankYou" }
);
Now when you navigate to /about/contact the Contact GET action will be executed (You have to rename it as in your code it is called ContactUs). Then the user fills the form and submits to the Contact POST action. The url stays the same for the moment: /about/contact. After the redirect the ThankYou action is executed and the url changes to /about/contact/thankyou.