How to move from one controller to next in Asp.net MVC - c#

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.

Related

RedirectToAction for index to go to example.com/controller/id

We are using a controller which has an "Index" action:
[Route("")]
[Route("Index/{id:int?}")]
[Route("{id:int?}")]
public ActionResult Index(int? id)
{
var viewModel = new GroupViewModel();
....
return View("Index", viewModel);
}
We can get to this action by using example.com/my/ or example.com/my/index or example.com/my/index/1. This works as we want. Now we want to redirect to this using the example.com/my/index/1 syntax.
When we execute this line:
return RedirectToAction("Index", "My", new { id = 3 });
It will redirect using this url:
example.com/my?id=3
We want it to use example.com/my/index/1 instead.
Does anybody know of a way to force RedirectToAction to use this convention without the question mark?
Updated 5/2/17 to correct controller names per comments below
You need to tell which route template you need to use for generating the URL for the redirection. For the moment you haven't an URL template that can generate a URL like /my/index/1 which is "My/Index/{id:int?}"
First,add that route template to your action and set the Name property of that route like this:
[Route("")]
[Route("Index/{id:int?}")]
[Route("My/Index/{id:int?}", Name = "MyCompleteRouteName")]
[Route("{id:int?}")]
public ActionResult Index(int? id)
{
var viewModel = new GroupViewModel();
....
return View("Index", viewModel);
}
Second, you must RedirectToRoute instead of RedirectToAction. RedirectToRoute let you choose which template you want by giving its name.
So you must call this line :
RedirectToRoute("MyCompleteRouteName", new { id = 3 });
Instead of
RedirectToAction("Index", "My", new { id = 3 });

Method Clear Cache DonutOutputCache

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.

Redirection error

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.

How to use RedirectToAction while passing view model to a view with different route

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.

How to pass a value from a controller method to an another?

I'm beginner in MVC3, and I want to get a value from an another controller's method. Here the two methods:
[HttpPost]
public ActionResult Create(TennisClub tennisclub)
{
if (ModelState.IsValid)
{
db.TennisClubs.Add(tennisclub);
db.SaveChanges();
return RedirectToAction("AssignManager");
}
return View(tennisclub);
}
[HttpPost]
public ActionResult AssignManager(Manager manager)
{
}
So, when I'm creating a new tennis club, Immediately I would like to assign a manager to it... For that I need the primary key "ID".
So my question is: How to get this ID in my "AssignManager" method ? Thanks in advance
You cannot redirect to an action decorated with the [HttpPost] attribute. That's not how a redirect works. A redirect means that you are sending a 301 HTTP status code to the client with the new Location header and the client issues a GET request to this new location.
So once you remove the [HttpPost] attribute from your AssignManager action you could pass the id as parameter:
return RedirectToAction("AssignManager", new { id = "123" });
and then:
[HttpPost]
public ActionResult AssignManager(int id)
{
}
Basically, you need to have a GET AssignManager method, too, which would have a parameter telling it to which TennisClub the manager should be assigned:
[HttpGet]
public ActionResult AssignManager(int tennisClubId)
{
// here, you will want to return AssignManager view
}
And when redirecting to AssignManager from Create, you can specify the id of TennisClub:
return RedirectToAction("AssignManager", new { tennisClubId = tennisclub.Id });
return RedirectToAction("AssignManager", new { id = tennisclub.Id });
Also you need to remove the [HttpPost] attribute from your action
public ActionResult AssignManager(int id) {
//...
}

Categories

Resources