RenderAction not finding action method in current controller in current area - asp.net

I'm creating an ASP.NET MVC 2 (RTM) project that uses areas. The Index action of the Home controller of one area needs to use RenderAction to generate a sub-section of the page. The action called is also defined in the same Home controller. So the call should just be:
<% Html.RenderAction("List") %>
However, I get an exception:
A public action method 'List' was not found on controller 'RareBridge.Web.Areas.Events.Controllers.HomeController'.
Note that I'm not in the "Events" area! I'm in a completely different area. If I remove the "Events" home controller, then the exception still occurs but names a different controller (still not the one I want it to call).
I've also tried providing the controller name and area to the RenderAction method, but the same exception occurs. What is going on here?
BTW: I am using Autofac as my IoC container

Probably action you call has filter attribute (i.e. AcceptVerbs) which doesn't match current request. Remove filters from "List" action and try again.

Use the renderaction overload which takes routeValues as parameter and use the area property to redirect to a specific area:
f.i.
<% Html.RenderAction("Edit", module.Value, new { area = "Modules", id = module.Key }); %>

Related

ASP.Net MVC Controller and View interaction

I created a sample MVC application using following Template.
ASP.NET MVC2 Empty Web Application
Then a added a Controller with the name of First and a right clicked the ActionResult to add a View.
I typed http://localhost:49565/First in my Browser.
Query
How is the controller internally getting to know that a specific page will be displayed when we will type http://localhost:49565/First ?
Moreover, If I add multiple Views for a Controller. How will the system decide which one will be displayed on Priority ?
The controller is invoked by the MVC framework, which uses the routes defined in Global.asax.cs to determine which controller and action to invoke. There is a default route that looks like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
When the application receives a request is will try to parse the URL to the format of the routes. If the request is made to http://localhost:49565/, it will use the default values which goes to the Index action in the controller named HomeController. When you have created the new controller, FirstController, and call http://localhost:49565/First, it uses the FirstController instead of the HomeController since it has been provided (but still to the Index action).
Further, when an action is being invoked and there is no view defined explicitly, it will look for a view named the same as the invoked action. In your case it would be ~/Views/First/Index.aspx.
EDIT
If you want to use another view you can specify it in the return statement
return View("OtherView");
and it will use ~/Views/First/OtherView.aspx instead.
Have a look at this blog posts give u the idea of how it is done

asp.net MVC 3 action method

I have created a partial view and I am using it in admin controller's Home action method. Inside partial view, I have an Account Controller with action method named Logon. I am trying to access main view's URL like this
if (Url.ToString().ToLower().Contains("/admin"))
return Redirect("/Admin/Index");
but I cant get the required result. How to get it admin/home ?
From the comments above it looks like you want to just access the current url. If so, then you can simply use the Request object. E.g.
Request.Url.AbsoluteUri
I wonder why you need this though... what is it you are trying to do exactly?

Asp.Net MVC Not Duplicate forms when Edit/Add

When we have anything that requires user input (Eg adding a product to a database) the Edit screen looks the same as the add screen. When using MVC .Net how do you handle this? Do you return the same view? Just adjust the model to reflect the change?
Same (partial)view
You create only one but strong typed view (depending on the UI it can of course be a partial view as well). When adding new data return this view from controller action with default model object instance (usually just a new instance without any properties being set), but when you edit, return it with the object instance that you'd like to edit.
Controller part
Regarding controller actions you can have four of them:
Add GET
return View("SomeView", new Customer());
Add POST
Edit GET
return View("SomeView", new CustomerRepository().GetCustomer(id));
Edit POST
Bot GET actions return the same view but with different model as described earlier. POST actions both store submitted data, but return whatever they need to. Probably some RedirectToAction()...
You can use the same view for display and Edit, simply call it from your controller
return View("ViewName")
You could have the form fields in a partial view and have two separate views using the same partial view, one posting to the edit controller action method and the other posting to the add controller action method.
Partial views are used to remove duplicity. You could read an example of this in the Nerd Dinner tutorial.

Html.ActionLink() gives me an empty link when I use it inside Html.RenderAction()

I have a Microsoft MVC project with an action "Foo" whose view ("Foo.aspx") contains the lines:
<%= Html.ActionLink("mylinktext1", "bar") %>
<%= Html.ActionLink<MyController>(x => x.Bar(), "mylinktext2") %>
When I hit this from a web browser or load it from an AJAX call, it properly returns:
mylinktext1
mylinktext2
But when I call the action from another view like this:
<% Html.RenderAction<MyController>(x => x.Foo()); %>
Then the links are rendered without targets.
mylinktext1
mylinktext2
Why would this be happening, and how do I work around it?
I don't know if that is what you are doing wrong, but I have never used Html.RenderAction with actions that return ASPX views. When I call RenderAction, I make sure that I am calling a controller action that returns ASCX View User Control.
Typically .ASPX file is an entire page and you can't (shouldn't) render this inside another page.
So I think you should make it View User Control (ASCX) and put it either in Shared or in controller's view folder.
Based on your comment:
Of course this is fine. You just return your data as model to your views/view user controls. When you load them thru AJAX, you should consider implementing Render View to String. Search the Google or Stack for more information on it. You can also search for a thing called JsonPox attribute for your action methods - also implemented somewhere on the internet. It will enable decorating your action methods so that they are able to return HTML view, XML or JSON if that's what you also might need.

How do you use usercontrols in asp.net mvc that display an "island" of data?

I am trying to find out how to use usercontrols in asp.net mvc. I know how to add a usercontrol to a view and how to pass data to it. What I haven't been able to figure out is how do you do this without having to retrieve and pass the data in every single controller?
For example, if I have a user control that displays the most recent posts on several but not all the pages in the site, how do I write the Controllers so that I get data for that usercontrol and pass it to the user control from only one place in the web site instead of getting and passing data in each of the different controllers that the user control is used in?
I'm not sure if this makes sense or not. Is there a better or recommended way to handle an "island" of data that you want to display on several pages?
I'm coming from web forms where I could just write a user control that got its own data and displayed data independently from the rest of whatever page it is used on.
There are multiple ways to do it.
The basic approach is
Populate the data for the view in the BaseController (OnActionExecuting event)
Writing a custom action filter
Writing an Application Controller (the eg. is in the below links).
An example of OnActionExecuting will be
[HandleError]
public class BaseController : Controller
{
CourseService cs = new CourseService();
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
List<Tag> tags = cs.GetTags();
ViewData["Tags"] = tags;
}
}
You can use the "tags" view data on any view. This is just an example of usercontrol being rendered as side content.
<div id="sidebar_b">
<asp:ContentPlaceHolder ID="ContentReferenceB" runat="server" >
<% Html.RenderPartial("Tags"); %>
</asp:ContentPlaceHolder>
</div>
I found the following URL to be useful.
http://weblogs.asp.net/stephenwalther/archive/2008/08/12/asp-net-mvc-tip-31-passing-data-to-master-pages-and-user-controls.aspx
http://blog.matthidinger.com/2008/02/21/ASPNETMVCUserControlsStartToFinish.aspx
http://www.aaronlerch.com/blog/2008/01/26/displaying-foo-on-every-page-of-an-aspnet-mvc-application/
http://blog.wekeroad.com/2008/01/07/aspnet-mvc-using-usercontrols-usefully/
In the MVC Futures, available on codeplex , contains the RenderAction HtmlHelper extensions. This will allow you to create a controller for the ueser control and this controller will populate the ViewData used by the user control without having to resort to a base controller as was suggested.
In the View you would do
<% Html.RenderAction("Index", "UserControlController") %>
or one of the other overloads.
This will create an instance of the controller, execute the method and render the user control view into the main view. The main view controller does not need to know anything about the user control or its model/data.
Refactor the code that obtains the view data for this user control into it's own method, maybe even it's own model (class). Call this method from each controller that needs to populate the control and pass the results in the ViewData with a well-known key. You might even want to pass the type of the current controller to your method in case it needs to know what data to retrieve based on the base model for the controller.
ViewData["RecentPosts"] = RecentPosts.GetRecentPosts( this.GetType() );
In your control, retrieve the data using the well-known key.
How to Handle "Side Content" in ASP.NET MVC

Resources