Setting masterName on MVC view causes error when calling RenderAction - asp.net-mvc-3

I have a Masterpage (site.master) that calls a View using RenderAction. At the moment the View returns "hello world".
site.master:
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<html>
<head id="Head1" runat="server">
<title><asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" /></title>
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server" />
</head>
<body>
<% Html.RenderAction("Test", "Charts"); %>
<asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server" >
<p>site.master</p>
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server" />
</body>
</html>
Test.aspx:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
hello world!
ChartsController.cs:
public ActionResult Test()
{
return View();
}
If I update the View to pass in the name of the Masterpage explicitly I get an error when I call RenderAction.
ChartsController.cs:
public ActionResult Test()
{
return View(null, "site");
}
Error:
Content controls have to be top-level controls in a content page or a nested master page that references a master page.
Stack Trace:
[HttpException (0x80004005): Content controls have to be top-level controls in a content page or a nested master page that references a master page.]
System.Web.UI.MasterPage.CreateMaster(TemplateControl owner, HttpContext context, VirtualPath masterPageFile, IDictionary contentTemplateCollection) +8857854
System.Web.UI.Page.get_Master() +54
System.Web.UI.Page.ApplyMasterPage() +15
System.Web.UI.Page.PerformPreInit() +45
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +328
How do I go about setting the master page that I want the view to use? Ultimately I will be setting the Masterpage dynamically using a custom ViewEngine (by overriding VirtualPathProviderViewEngine.FindView).
if ( String.IsNullOrEmpty(masterName) ){ masterName = "site"; }
When I set the masterName property in my ViewEngine and then call RenderAction from site.master I get the same error as when I set the masterName property in the Action.
I am using:
Visual Studio 2010
MVC 3
IIS Express
edited: added full site.master markup

Subclass ViewPage<T> and override the OnPreInit() event. In your override,
protected override void OnPreInit(EventArgs e)
{
this.MasterLocation = GetMasterLocation();
base.OnPreInit(e);
}
The GetMasterLocation() method should get the filename of the view (beginning with a "~/").
The error comes from the CreateMaster method in MasterPage, the code that throws it is:
if (masterPageFile == null)
{
if ((contentTemplateCollection != null) && (contentTemplateCollection.Count > 0))
{
throw new HttpException(SR.GetString("Content_only_allowed_in_content_page"));
}
return null;
}
So, the MasterPage doesn't exist and content template collection has templates, so the page throws an exception. Following the above instructions will programmatically set the masterpage's location (which gets processed into the virtual path which is the variable masterPageFile)

I have come up with a solution and at least a partial answer/understanding to the cause of my issue.
If I am correct the issue is that I as trying to set the Masterpage on a view that didn't have/need a Masterpage. I think that the result was that I was setting a path to a Masterpage and even though that Masterpage exists the View was not expecting it and through an error.
When I updated the View to use a Masterpage I was able to pass the name of the Masterpage directly to the View without an error.
Test.aspx:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Charts.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
hello world!
</asp:Content>
The way that I resolved this in my custom ViewEngine was to check if the current View is a ChildAction.
if (String.IsNullOrEmpty(masterName) && !controllerContext.IsChildAction)
{
masterName = "site";
}

Related

How to prevent DNN Skin AddModule Message from auto-scrolling the page?

The DNN DotNetNuke.UI.Skins.Skin.AddModuleMessage method causes the page to auto scroll on Postback. I am using DNN 9.01.01
I did try MaintainScrollPositionOnPostBack, but it seems like you can't use this in a Master page:
https://forums.asp.net/t/1038248.aspx?MaintainScrollPositionOnPostBack+true+IN+MASTER
<%# Control Language="C#" MaintainScrollPositionOnPostback="true" AutoEventWireup="true" CodeBehind="Default.aspx.cs" %>
This is the method that is causing the trouble in DNN:
private void AddModuleMessage(ModuleMessage.ModuleMessageType moduleMsgType, string Message, bool error = true)
{
if (error)
{
moduleMsgType = ModuleMessage.ModuleMessageType.RedError;
}
DotNetNuke.UI.Skins.Skin.AddModuleMessage(plcMessages, Message, moduleMsgType);
}
I have tried to disable Focus() on inputs, but it does the same.
Here are other sources I looked at https://www.dnnsoftware.com/forums/threadid/284691/scope/posts/when-page-loaded-the-browser-scrolls-down
Also, does Update Panels cause auto scrolling?

Session is null when redirect from one controller to another ASP.NET MVC

Why Session is null when redirection from one controller to another? And when I refresh the page again I find that the session object is not null and have data!
First controller:
HttpContext.Session["SiteCheckpoint"] = siteCheckpoint;
//redirect to second page controller
Response.Redirect(siteCheckpoint.FirstPageUrl + "?rf =" + referenceId);
Second controller:
if (HttpContext.Session[Resources.SessionParameter.SiteCheckpoint] != null)
{
GetCheckpointData();
}
else
{
//Raise error page
}
I tried this solution but it didn't work:
<remove name="Session" />
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
i solved my issue since i wasn't define any model in my view i can't pass any data to the second controller
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<BCV4.Web.Redirection.Models.HomeModel>" %>

Updating result from ajax calls in partial views in asp.net mvc2

I have a ASP.Net MVC 2 partial view like the one below,
FORM 1:
<div id="d1">
<% using (Ajax.BeginForm("ManageSources", "Sources",
saveAjaxOptions))
{ %>
... all this form's html markup goes here
<div id="src_Parameters"></div>
<% } %>
</div>
Form 2
<% using (Ajax.BeginForm("FetchParameters", "Sources",
fetchAjaxOptions))
{ %>
hidden fields to send values to the action method go here
.. button to post this form
<% } %>
Now, in the fetchAjaxOptions, i have given the target div to be src_Parameters, which resides inside the form1, when i post the second form, i am being returned a partial view as the only view page, instead of populating the results in the src_Parameters div.
How do i accomplish this. Actually the results of the FetchParameters ajax call should be able to be posted for the ManageSources ajax call.
Where is the problem or will nesting the forms workout since this is using ajax forms.. Kindly suggest me the right procedure to do this task.
You haven't posted your server side code, but I suspect you have forgotten to have set the return type to be a partial view.
public PartialViewResult FetchParameters()
{
//do some stuff
return PartialView(“_ViewName”, viewModel)
}
It could also be that you fotgot to add a reference to the Microsoft Ajax
<script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>

populate one dropdown on selection of other using struts2 dojo tags

I have two dropdowns. I want to populate the second dropdown on selection of first dropdown.
I am using struts-dojo-tags for accomplishing this.
<%# page contentType="text/html; charset=UTF-8"%>
<%# taglib prefix="s" uri="/struts-tags"%>
<%# taglib prefix="sx" uri="/struts-dojo-tags"%>
<html>
<head>
<title>Welcome</title>
<script>
</script>
<sx:head />
</head>
<body>
<h2>Struts 2 + Ajax Example 2!</h2>
<s:form name="f1">
<s:textfield name="proj" label="Project Name" />
<s:url id="url" value="/populateStates.action" />
<s:select id="id1" list="countryList"
listKey="countryId" listValue="countryName" headerKey="0"
headerValue="-Select-" label="Country"/>
<s:select id="id2" list="list2" listKey="stateId"
listValue="stateName" headerKey="0" headerValue="-Select-"
label="State" />
<sx:bind sources="id1" targets="id2" events="onchange"
href="%{#url}" />
</s:form>
<br>
</body>
</html>
My action class has two action methods.
public String populateCountry() throws Exception{
list1 = new ArrayList<Country>();
list1.add(new Country(1, "Country1"));
list1.add(new Country(2, "Country2"));
list1.add(new Country(3, "Country3"));
return SUCCESS;
}
public String populateStates() throws Exception{
System.out.println("populateStates******************"+id1);
list2 = new ArrayList<State>();
if (id1 != null && !id1.equals(""))
{
if(id1.equals("1"))
{
list2.add(new State(1, "UMB1"));
list2.add(new State(2, "UMB2"));
list2.add(new State(3, "UMB3"));
}
else if(id1.equals("2"))
{
list2.add(new State(4, "UMB4"));
list2.add(new State(5, "UMB5"));
list2.add(new State(6, "UMB6"));
}
else if(id1.equals("3"))
{
list2.add(new State(7, "UMB7"));
list2.add(new State(8, "UMB8"));
list2.add(new State(9, "UMB9"));
}
}
return SUCCESS;
}
First action method is called when the jsp is loaded the first time (with populated Country drop down) and second action method is called when I select a country from the Country dropdown.
Problem: States drop down is not getting populated. When I debug the code, I see that when control reaches populateStates all the variables of my Action class are reset(id1, id2, list1, list2, proj). Due to which I get an empty States dropdown. Please help me to solve this issue.
I don't think <sx:bind> does what you think it does; the target's HTML will be replaced by what the action returns.
You could try returning just the list of <option>s (and perhaps that's what you're doing), but I don't believe it would work. (If it does, definitely follow up with your own answer.)
I'd actually recommend using the jQuery plugin; the Dojo tags have been deprecated for some time, use a very outdated version of Dojo, and often a pain to work with.
Another option would be to just use plain old jQuery (or library of your choice)--it's almost always easier than implementing custom functionality via a tag library. The Ajax tag libraries are great for really simple usecases, but as soon as there's anything custom, I'm not convinced they save much effort. YMMV.

MVC 3: Add usercontrol to Razor view

I have a DLL that contain a user control inside, in the Web Form view i can easily use it by using
<%# Register Assembly = "..." Namespace = "..." TagPrefix = "..." %>
But how to do it in Razor view?
You can't add server side controls to Razor views. In general it is very bad practice to do so anyways in an ASP.NET MVC application. Due to the heritage of WebForms view engine you could violate this rule but in Razor things have been made clearer.
This being said you could still do some pornography in Razor and include a WebForms partial which will contain the user control (totally not recommended, don't even know why I am mentioning it but anyway):
#Html.Partial("_Foo")
where in _Foo.ascx you could include server side controls:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%# Register Assembly="SomeAssembly" Namespace="SomeNs" TagName="foo" %>
<foo:SomeControl runat="server" ID="fooControl" />
Also, not recommended, but you can render a control in code, like in an HTML Helper:
public static string GenerateHtmlFromYourControl(this HtmlHelper helper, string id)
{
var yourControl = new YourControl();
yourControl.ID = id;
var htmlWriter = new HtmlTextWriter(new StringWriter());
yourControl.RenderControl(htmlWriter);
return htmlWriter.InnerWriter.ToString();
}
and then you can reference it from your view:
Html.GenerateHtmlFromYourControl("YourControlId")
Just make sure you set up/reference your namespaces correctly to do this.
Caveat
FYI, I'm pretty sure there are some severe limitations regarding the Page Lifecycle here...

Resources