passing the original controller and action name - mvc - asp.net-mvc

I have an ascx control for fruits that contains following code:
<div id = "fruits">
....
Ajax stuff1 UpdateTargetId = "fruits"
Ajax stuff2 UpdateTargetId = "fruits"
<%Html.RenderPartial("PagerAjax", (Pager)ViewData["pager"]); %>
</div>
now this fruit control can appear on a number of webpages and the pager would need to know what page the user is on so that it can pull next set of fruits accordingly. For example, if I am on red-fruit page, then PagerAjax should know I am only pulling out red fruits. So, basically I would need to know ControllerName (assume it's home) and actionName (assume it's redFruits()). (Example may seem inefficient but it makes sense for the real purpose.) Now, I could do something like this:
<%Html.RenderAction("PagerAjax", (Pager)ViewData["pager"], ViewContext.RouteData.Values["action"], controllerFilter = ViewContext.RouteData.Values["controller"] }); %>
However, as you noticed, the above RenderAction is inside the div that is being updated by Ajax callback, which means it will contain action and controller of the Ajax stuff rather than the original URL's.
What should be an efficient workaround?

You could pass the original ViewContext.RouteData.Values["action"] as parameter when calling your AJAX action. This way the action knows what was the original action and store it in the model (or ViewData as in your case I see that your views are not strongly typed). Now your markup could become:
<% Html.RenderPartial(
"PagerAjax",
(Pager)ViewData["pager"],
new ViewDataDictionary() { { "originalAction", ViewData["originalAction"] } }
); %>

Related

#RenderPage - Render a edit page

I want to render a page but that page be a "edit" page. Something like this
#RenderPage("~/Views/Edit/25.cshtml")
But this doesn't work and probably i should pass the parameter "25" as a parameter, but so far without success. In my program I've got two tabs and both call(render) pages throw Ajax (Jqueryui - http://jqueryui.com/tabs/) and i would like to when i click in a tab he call the edit view with a specific id.
It's possible? How i should do that?
To render tabs via ajax in asp.net mvc you can do it this way.
CSHTML:
Create tab control, each anchor in tab header uses different routevalues. Ofcourse you can link them to different actions of controller:
<div id=tabs>
<ul>
<li>#Html.ActionLink("Tab1", "Edit", new { id = 25 })</li>
<li>#Html.ActionLink("Tab2", "Edit", new { id = 26 })</li>
</ul>
</div>
Controller, note that you are returning a partial view here which gets rendered into the tabcontrol:
public ActionResult Edit(int id)
{
// You probably want to load the Model from the db with id param. I just write a message
ViewBag.Message = id;
return PartialView("Edit");
}
My partialview Edit.cshtml:
<span>Edit me #ViewBag.Message</span>
Javascript, just create your tab control normally:
$("#tabs").tabs();
Generally if you want to render some partial view with parameters I'd personally go for
#Html.Action("Edit", "Controller", new {id=25})
If you want some actions to be performed on click for the specific tab then i would suggest you should go with Ajax.
Have a look to jQuery.Ajax.
Or else you want it a pure http web request, then you can have certain query string to be passed on the same page when user clicks on the tab and load the content accordingly by identified the passed value.

ASP.NET MVC 2: ViewData.Model.ExecuteResult not existing

ViewData.Model.ExecuteResult does not exist in ASP.NET MVC2, but in MVC1.
What is the alternative in ASP.NET MVC2?
What I want to do, is to update a table after an ajax request. So I put the table in an extra View. How can I update this partial view without loading the whole page again?
ExecuteResult is a method on the System.Web.Mvc.ActionResult class. Are you sure you don't mean to be looking there?
http://aspnet.codeplex.com/SourceControl/changeset/view/23011#266522
The Model property is just an object type, and always has been, AFAIK.
As for updating the table, what I've done in the past, to update a portion of a page after a partial view is to use Ajax.BeginForm like so:
<% using (Ajax.BeginForm("Customers", new AjaxOptions { UpdateTargetId = "customerList"})) { %>
<!-- FORM HERE -->
<% } %>
<div id="customerList">
<% Html.RenderPartial("CustomerList"); %>
</div>
'UpdateTargetId' is the key here, and tells MVC to use the result of the "Customers" action to replace (by default, you can append by setting the InsertionMode AjaxOption to InsertBefore or InsertAfter) everything inside the element withthe Id you specify.
If you want to use the same action to service the full page request and the Ajax request, you can use the IsAjaxRequest extension method to determine what to return:
if (Request.IsAjaxRequest())
return PartialView("CustomerList");
// Not an Ajax request, return the full view
return View();
Hope that helps!

how to call controller from button click without using ajax mvc

I'm new to web programming in general so this is probably a really simple question. I couldn't find anything on the web however.
What I want to do is call my controller with the typed search string and return the results from a database and paginate the results. Right now I am using a function that is called when the button is pressed. The function looks like so:
function SubmitSearch() {
var searchBox = document.getElementById('searchBox');
var searchButton = document.getElementById('SearchButton');
$.post("MyController/MyAction/",
{
searchString: searchBox.value,
page: null
}, function(result) {
$('#searchResults').html(result);
searchButton.value = "Search";
});
}
What happens is my controller is called, and my searchResults div is populated with the results and paginated. The user can click any search result returned to view the details.
The problem is when the user clicks the browsers 'back' button, the page returns to the state before the search was entered, and this is because of the ajax call. What I want to do is, call the controller and have the page load like google would. Instead of using a PartialView, I would use a View (my guess).
How would I call the controller and have the page RELOAD with the results. I must be missing something fundamental because this definitely seems like it should be easy.
If you don't want to use AJAX then you need to place your text field in a form element on your page, something like:
<form action="MyController/MyAction/" method="get">
<input id="SearchBox" name="SearchBox" type="text" />
<button type="submit">Search</button>
</form>
Then in your controller return the view with the list of results.
You probably also want to look into RESTful URLs and the PRG (Post, Redirect, Get) pattern to maintain the integrity of the back button and enable correct bookmarking of pages etc.
I think you might actually be looking for an AJAX History library to help when the Back button is pressed rather than altering your app. Take a look at this blog post.
Aspx:
<% using (Html.BeginForm<MyController>(m => m.MyAction(null)) { %>
<%= Html.TextBox("q"); %>
<% } %>
// Listing
Controller:
public class MyController : Controller
{
public ActionResult MyAction(string q)
{
var repository; // instance of your repository.
if (String.IsNullOrEmpty(q))
{
return View(repository.GetAllBlogs());
}
return View(repository.SearchBlogs(q));
}
}

Render action return View(); form problem

I'm new to MVC, so please bear with me. :-)
I've got a strongly typed "Story" View. This View (story) can have Comments.
I've created two Views (not partials) for my Comments controller "ListStoryComments" and "CreateStoryComment", which do what their names imply. These Views are included in the Story View using RenderAction, e.g.:
<!-- List comments -->
<h2>All Comments</h2>
<% Html.RenderAction("ListStoryComments", "Comments", new { id = Model.Story.Id }); %>
<!-- Create new comment -->
<% Html.RenderAction("CreateStoryComment", "Comments", new { id = Model.Story.Id }); %>
(I pass in the Story id in order to list related comments).
All works as I hoped, except, when I post a new comment using the form, it returns the current (parent) View, but the Comments form field is still showing the last content I typed in and the ListStoryComments View isn’t updated to show the new story.
Basically, the page is being loaded from cache, as if I had pressed the browser’s back button. If I press f5 it will try to repost the form. If I reload the page manually (reenter the URL in the browser's address bar), and then press f5, I will see my new content and the empty form field, which is my desired result.
For completeness, my CreateStoryComment action looks like this:
[HttpPost]
public ActionResult CreateStoryComment([Bind(Exclude = "Id, Timestamp, ByUserId, ForUserId")]Comment commentToCreate)
{
try
{
commentToCreate.ByUserId = userGuid;
commentToCreate.ForUserId = userGuid;
commentToCreate.StoryId = 2; // hard-coded for testing
_repository.CreateComment(commentToCreate);
return View();
}
catch
{
return View();
}
}
The answer is to use return RedirectToAction(). Using this enforces the PRG pattern and achieves my goal.
My earlier comment to my original post did cause an error, that I guess I'm still confused about, but this works:
return RedirectToAction("Details", "Steps", new { id = "2" });
I, and this is a personal opinion, think you've tackled this the wrong way.
Personally I would;
Create a view called ListStories.
Create a partial view that lists the
stories.
Create a partial view to create a
story.
When you want to add a story, simply
show the add story html.
Then when the user presses a button
you do a jQuery postback, add the
new story and return a PartialView
of either the new story or all the
stories.
If you return a partial view of all
stories then replace the bounding
div that contains all the stories
with the new data.
If you return only a single story
then append it to the end of the div
containing the stories.
I know this means a lot of re-work and it sounds complex and like a lot of work but doing it like this means greater flexibility later on because you can re-use the partial views or you can make a change once and all views using that partial view are now updated.
also, using jQuery means that the adding of stories looks seemless w/out any obvious post back which is nice.
Since the problem seems to be caching, you can simply disable/limit caching.
Add the following attribute to your actions:
[OutputCache(Duration = 0, VaryByParam = "none")]
This will tell the browser to cache the page, but for 0 seconds. When the post reloads the page, you should see the desired results.
The answer is to make sure your form action is properly set. If you have used renderaction and not set the form controller and action manually then the action will be the current URL.
Try:
<% using (Html.BeginForm("ActionName", "ControllerName")) {%>
Instead of:
<% using (Html.BeginForm()) {%>

How can I use Html.ValidationSummary with Ajax.BeginForm?

I have an AJAX form that I am creating in my MVC project. If the form is submitted using normal browser function and a page refresh occurs I get validation information rendered in the form (the built in MVC validation based on ViewData.ModelState).
Is there a similiar validation mechanism for AJAX forms?
<% using (Ajax.BeginForm("Create", "GraphAdministration", new AjaxOptions()
{
OnSuccess = "newGraphSuccess",
OnFailure = "newGraphFailure",
HttpMethod = "POST"
}))
{ %>
<!-- some form stuff in here !-->
<% } //end form %>
It really depends on where you are getting the content from to display once the form has been posted. The Validation summary is performed created on the server so that is where you have to do the work.
As an example I was using some partial content in an .ascx file to render a form. You get the form in the page the first time round by calling the action directly with Html.RenderAction
You would have your Ajax.BeginForm etc. in the .ascx file. Then call it directly in an action.
When the Ajax call is made from the browser you get it to post to the same action. That way you can do all of the server side validation that you would normally. You should set up the Ajax call to replace the original form with the new html that is returned by the action.
One thing that you have to be aware of is that the replace JavaScript will replace the content of an element not the element itself so remember to us the id of a surrounding element.
Apologies if that is a little convoluted, if you want more details just comment and I'll flesh out the relevant bits.
Extra Detail:
All of this assumes that you are doing all of the validation on the server.
You are going to have a View that has all of the page stuff in it and then some partial content in a .ascx file, this is where your ajax form lives, it needs to be set to replace content by id. Its easiest if it has the same name as the action your ajax is going to call.
You can use Html.RenderAction to get it into the View. You can also pass in data with other versions of the same method. Your essentially calling it in the same way your ajax code will.
You will need to wrap it all in a div with an id set. Use this id in the partial as the content to replace.
When you render the page the html for the form and all of the ajax stuff will get put in.
When the ajax action is called the partial content will be returned with any validation performed. It will replace the content of the div that you gave the id to.
You can have different versions of the action by using [AcceptVerbs(HttpVerbs.Get)] and [AcceptVerbs(HttpVerbs.Post)] attributes
The main problem with this method is that its not self contained, the div with the id is external to the partial.

Resources