Why does RedirectToAction have no effect - asp.net-mvc-3

When the method with the barcode parameter is called, RedirectToAction has absolutely no effect. I can see that it does indeed return to that route in the URL, but the model is not refreshed and it displays stale data.
In the SQL Server profiler I can see that the call isn't being made to pull back the new data.
How can I force this to happen?
Incidently, the call to: public ActionResult SRScanItem(string barcode) is itself the result of a RedirectToAction from another controller.
I have handful of calls to RedirectToAction("SRPickCollectionItems") elsewhere in the same controller and these all work fine.
Any idea what may be causing this?
public ActionResult SRPickCollectionItems()
{
IEnumerable<ISRPickingItemSummary> items =
SRPickingItemsViewModel.
GetDisplayableChunk(ApplicationState.CollectionId.ToString(),
ApplicationState.AssistantNumber);
return View(items);
}
public ActionResult SRScanItem(string barcode)
{
DataLayer.Instance.AddStockroomFoundItem(barcode, ApplicationState.CollectionId, ApplicationState.AssistantNumber);
return RedirectToAction("SRPickCollectionItems");
}

Maybe the redirect is going to a cached page.
Could you try and decorate SRPickCollectionItems with
[OutputCache(Duration = 0)]

You don't seem to returning to a post method, only a get so it is not obvious how the method with the Redirect is getting called unless you are send the barcode as a query string parameter in a get call through an actionlink or link tag.
Normally you would have two methods named SRPickCollectionItems. The Get method (which you already have) loads the view and the post method (that you are missing) processes the postback. The post method would be thus...
[HttpPost]
public ActionResult SRPickCollectionItemsstring barcode){
DataLayer.Instance.AddStockroomFoundItem(barcode, ApplicationState.CollectionId, ApplicationState.AssistantNumber);
return RedirectToAction("SRPickCollectionItems");
}

Related

MVC & ajax: Should I create more views?

I'm developing an MVC3 application with EF and I wanted to make the UI fluent using jQuery ajax, the user will be able to navigate through the url, if he knows it or maybe he might receive a link pointing to a particular route, but, once the page is fully loaded it needs to be fluent, so I came up with one idea and I would like to discuss it here before I make the changes to the solution.
Here is what I came up with:
TestController.cs (Methods code has been omitted for simplicity)
public ActionResult Index() { ... }
public ActionResult Create() { ... }
[HttpPost]
public ActionResult Create(Test test) { ... }
public ActionResult Update(int testID) { ... }
[HttpPost]
public ActionResult Update(Test test) { ... }
public ActionResult Delete(int testID) { ... }
[HttpPost]
public ActionResult Delete(Test test) { ... }
So far it looks like most controllers. My views are as follows:
Views\Test\List.cshtml
Views\Test\Create.cshtml
Views\Test\Details.cshtml
Views\Test\Delete.cshtml
Now since I wanted to do it async: I've changed my List view so I could add, modify and remove from the list, so far is working like a charm. Plus, the user could still be able to navigate through the application using the url's, note that every link inside the application will perform an ajax request to do the actual work, there are no Route/Action links.
By now the application is working as expected, but now I came across something: there are views that I need to be ActionResult and PartialViewResult, that is because the user could type in the url: "/Admin/Test", which should return the full page, or could click on an anchor which will load only the content of the "/Admin/Test" and display it. To avoid the famous page inside page errors I wrote a function to send the request, and when the request arrives it selects only what I need, avoiding then the page inside page, and to duplicate views, but, the response is the whole page which, I don't need to say, it's not the best option, but since the application will be used by lan I didn't care too much about the payload of the response, but then I needed to write javascript code inside the views, so my solution was like null because using the jQuery selector to get only what I need the javascript wasn't there.
As for my new solution to solve my last solution:
I thought I might leave the original view as is, and create another view appending the word "Partial" after the original name, creating another method in the controller with the same naming convention, plus adding the new Route to my Route Table.
To wrap things up, what I need is the following:
- If the user types in "/Test" the response should be the entire page, loaded like the old days, screens flashing white and such.
- But if the user clicks the Test link in the navigation bar, the response should be async and refreshing only the content of my layout.
Any ideas? thoughts? suggestions?
In your actionmethod you can have
if (Request.IsAjaxRequest())
return PartialView("_somePartialView");
else
return PartialView("_someOtherPartialView");

MVC3 Why do I get "Child actions are not allowed to perform redirect actions" error?

I got an action List
//[HttpGet] (will come back to that!)
public ViewResult List(int page = 1)
{
//blah blah blah
return View(viewModel);
}
In its view we render action:
#{
Html.RenderAction("UpdateSearch");
}
Action definitions:
[ChildActionOnly]
[HttpGet]
public PartialViewResult UpdateSearch()
{
// do something and display a form in view
return PartialView(so);
}
[HttpPost]
public RedirectToRouteResult UpdateSearch(Options searchOptions)
{
// do something and redirect to List
return RedirectToAction("List");
}
and I'm getting: Child actions are not allowed to perform redirect actions exception every time someone submits the form. I'm new to MVC3, but it looks like the redirection is also a POST, because if [HttpGet] above List method is uncommented "the resource cannot be found" happens.
How do I change Http method on redirection or am I doing something wrong? I did try to Bing it, but no success.
The redirect info is stored in response header. However, the response is already being sent when child action is run so headers can't be written.
In short, there's no way of performing a redirect from child action other than through the use of javascript on client side.

Is there a simple way to pass data into an MVC3 app?

[Edit] To try to clarify:
I have a view that needs to be launched from an external application. The application requires string data to be passed from an external application (the data is free text and too long to pass as a query parameter), So I would like to launch the MVC application with a POST request. The view that is launched also needs to post data back to itself in order to submit the data it collects for storage in a database. So I end up with a View with two HttpPost flagged methods in my controller (MVC throws an error that there are ambiguous Create methods).
So in the code below Create() would be posted to from the external application. Create(FormCollection collection) would be posted to when a displayed View is submitted.
//POST: /Application/Create
[HttpPost]
public ActionResult Create()
{
MyModel model = new MyModel();
//Parse External Data to model from Request.InputStream
return View(Model);
}
//POST: /Application/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
//Save form collection data to database
return RedirectToAction("Index");
}
So long story short, how can I post data to an MVC application to launch a view, without getting an error for an ambiguous call.
Thanks.
in the first case when the post method comes in from the outside:
return View("ConfirmCreate", model)
Then create an action method named ConfirmCreate. After ConfirmCreate is called the second time you will redirect back to Index as you have.
So I was able to do this by changing the POST call to load the application to a PUT To avoid have duplicate post endpoints), then sending the PUT from an ajax call in another application and replacing the current document with the returned html from the successful ajax call. Thanks for the suggestions.

Weird MVC Issue

I have this code and I can't understand why it works this way
I have a model and view which is arbitrary and a very simple (but weird) controller
Here is my controller:
public partial class RouteController : Controller
{
[HttpGet]
public virtual ActionResult Create()
{
Create create = new Create();
return View("Create", create);
}
[HttpPost]
public virtual ActionResult Create(Create route)
{
return Create();
}
}
The first create method loads the view as normal. When the view posts back it runs the 2nd action which runs the first (as expected). The wierd part is the view is (re-)loaded with my previously entered data with errors (if any). I dont understand this because my model is empty. I was expecting it to post back with the same form as if it was loaded for the first time but with errors possibly.
Please explain.
That's the normal behavior of HTML helpers and it is by design. They first look at values contained in the ModelState and after that in the actual model. If you intend to modify some values on the model in a POST action you need to remove them from modelstate first:
For example:
[HttpPost]
public virtual ActionResult Create(Create route)
{
ModelState.Remove("SomeProperty");
route.SomeProperty = "some new value";
return View(route);
}
If you intend to completely modify everything as in your example you could clear the modelstate entirely:
[HttpPost]
public virtual ActionResult Create(Create route)
{
ModelState.Clear();
return Create();
}
Another possibility is to write your own TextBoxFor, HiddenFor, CheckBoxFor, ... helpers that will use the value in the model and not the one in the model state. Or yet another (non-recommended) possibility:
<input type="text" name="SomeProperty" value="#Model.SomeProperty" />
Of course in this case client validation among other things provided by the standard helpers won't work.

Persisting Data from one controller to another

Hey guys,
What is the best mechansims for persisting viewmodel data from one controller to another.
For instance
return RedirectToAction("SomeAction", "SomeController");
I need to have some data from the previous controller available to the new controller I am redirecting to.
If you are not passing an object or something complex, make use of parameters. Just make sure redirected action gets parameters to display what it should.
return RedirectToAction("SomeAction", "SomeController",new { id=someString} );
Get the parameter in the action:
public ActionResult SomeAction(string id)
{
//do something with it
}
#Ufuk Hacıoğulları: You can't share information between 2 controllers using ViewData. ViewData only shares information between Controller and View.
If you need to share complex information between multiple Controllers while redirection, use "TempData" instead.
Here is how you use "TempData" - http://msdn.microsoft.com/en-us/library/dd394711.aspx
A redirect is going to send an http response to the client that directs it to then make a new http request to /SomeController/SomeAction. An alternative would be for you to call a method on your other controller directly... new SomeController().SomeAction(someData) for example.
I think this will be helpfull to you to pass value from one action to another action .
public ActionResult ActionName(string ToUserId)
{
ViewBag.ToUserId = ToUserId;
return View();
}
public ActionResult ssss(string ToUserId)
{
return RedirectToAction("ActionName", "ControllerName", new { id = #ToUserId });
}

Resources