I'm trying to get my content page to be able to access an ASP:Literal on a master page.
I have my content page as:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="viewProduct.aspx.cs" Inherits="AlphaPackSite.viewProduct" Title="Hi there!" %>
<%# MasterType TypeName="Main" %>
Then my master page called Main.master has:
<asp:Literal runat="server" ID="lblBasket" />
But from the content page when I try and do:
Master.basket.Text = "test";
I get:
Error 46 The type or namespace name
'Main' could not be found (are you
missing a using directive or an
assembly reference?)
The error is on the designer page:
public new Main Master {
get {
return ((Main)(base.Master));
}
}
My master page code behind is:
namespace AlphaPack.MasterPages
{
public partial class Main : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
this.IsLoggedIn = Request.IsAuthenticated;
}
public bool IsLoggedIn
{
get { return this.ViewState["isLoggedIn"] as bool? ?? false; }
set { this.ViewState["isLoggedIn"] = value; }
}
}
}
Is the designer within your AlphaPack.MasterPages namespace?
The MasterType isn't fully qualified, should it be? Don't you have to provide a path as well? (Not familiar with, sorry).
How does this respond if you use a MasterPageFile reference instead of a MasterType?
<%# Page Language="C#" MasterPageFile="~MasterPages/Main.Master" AutoEventWireup="true" CodeBehind="viewProduct.aspx.cs" Inherits="AlphaPackSite.viewProduct" Title="Hi there!" %>
<%# Page MasterPageFile="~/MasterPages/Main.master" .. %>
<%# MasterType VirtualPath="~/MasterPages/Main.master" .. %>
Okey, that's how it looks in my own app:
Master page (Site.master, in the root):
<%# Master Language="C#" AutoEventWireup="True" CodeBehind="Site.master.cs" Inherits="Project.SiteMaster" %>
It's code-behind:
namespace Project
{
public partial class SiteMaster : System.Web.UI.MasterPage { }
}
Content page (Test.aspx, in the root):
<%# Page Language="C#" AutoEventWireup="True" CodeBehind="Test.aspx.cs" Inherits="Project.Test" MasterPageFile="~/Site.master" Title="Test" %>
it's code-behind:
namespace Project
{
public partial class Test : System.Web.UI.Page { }
}
That's how auto-generated code looks like:
namespace Project {
public partial class SiteMaster {
/// <summary>
/// lblBasket control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Literal lblBasket;
}
}
So create a property but don't share the control itself, only text:
public string BasketText
{
get { return this.lblBasket.Text; }
set { this.lblBasket.Text = value; }
}
Related
The abstract problem: I'm trying to limit user input in text fields to the same as the database length of the column. So I want to set a maxlength attribute on an html input, and the maxlength should be the same as the max length allowed in the database. I could hardcode these constants throughout the frontend, but I'm trying to set that value dynamically.
The problem: telerik RadComboBox won't accept an asp code block to set a property. The exception is as follows:
Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Cannot create an object of type 'System.Int32' from its string representation '<% Utility.GetColumnMaxLength<Portfolio>(x => x.Title) %>' for the 'MaxLength' property.
I've created a new minimal asp.net project to duplicate the problem. default.aspx source (no .cs code behind):
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TelerikCodeBlock._Default" %>
<%# Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<%# Import namespace="TelerikCodeBlock" %>
<%# Import namespace="TelerikCodeBlock.DataModel" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<telerik:RadComboBox ID="txtboxTitle" runat="server" MaxLength="<% Utility.GetColumnMaxLength<Portfolio>(x => x.Title) %>" >
</telerik:RadComboBox>
</asp:Content>
The Utility class has been minimized to the following
namespace TelerikCodeBlock
{
public class Utility
{
public static int GetColumnMaxLength<T>(Expression<Func<T, object>> property)
{
// looks at Entity Framework metadata in real project ...
return 3;
}
}
}
Data model looks like
namespace TelerikCodeBlock.DataModel
{
public class Portfolio
{
public int Id { get; set; }
public string Title { get; set; }
}
}
Possible workaround: using ASP.NET Expressions (the <%$ ... %> code blocks), build a general expression that executes code, as outlined here.
Add a reference to Microsoft.CodeDom.Providers.DotNetCompilerPlatform.
Define the following somewhere:
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Compilation;
using System.Web.UI;
namespace TelerikCodeBlock
{
[ExpressionPrefix("Code")]
public class CodeExpressionBuilder : ExpressionBuilder
{
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,
object parsedData, ExpressionBuilderContext context)
{
return new CodeSnippetExpression(entry.Expression);
}
}
}
And register it in the web.config
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" >
<expressionBuilders>
<add expressionPrefix="Code" type="TelerikCodeBlock.CodeExpressionBuilder"/>
</expressionBuilders>
</compilation>
...
Now change the asp control to use the expression code block:
<telerik:RadComboBox ID="txtboxTitle" runat="server" MaxLength="<%$ Code: Utility.GetColumnMaxLength<Portfolio>(x => x.Title) %>" >
I started up a Default MVC 4 project using the ASPX engine (not Razor), and everything works fine.
I can use
<% Model.Name %>
and
<% Model.Rating %>
for book ratings (instead of the Restaurant Review that is up on the asp.net/mvc tutorials site). However, my code errors on the
<% ViewBag.Message %>
...so for some reason, when inheriting from the "BookReviewer" Class within the BookReview model, I can view the Model information but not the Viewbag? Am I missing something? Code below.
[Controller]
HomeController.cs:
public class HomeController : Controller
{
var model = new BookReview()
{
Name = "Pro jQuery For Noobs",
Rating = 7
};
return View(model);
}
[Model]
BookReview.cs
namespace Bookreview.Models
{
public class BookReview
{
public string Name { get; set; }
public int Rating { get; set; }
}
}
[View]
Index.aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<BookRevew.Models.BookReviewer>" %>
<asp:Content ID="indexFeatured" ContentPlaceHolderID="FeaturedContent" runat="server">
<h2>
<% ViewBag.Message %>
<% Model.Name %>
<% Model.Rating %>
</h2>
</asp:content>
As we can see by your comments, you are setting the ViewBag.Message in another controller. The ViewBag is only for data for the view that was set by the controller that served the view.
If you need to send it from another controller, you should use a parameter in your action method, then you can set the ViewBag.Message to the passed in parameter.
Does anyone have any idea how to solve this problem please?
This is the Parser Error When I Run the Application:
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: 'FCR2.abs' is not allowed here because it does not extend class 'System.Web.UI.Page'.
Source Error:
Line 1: <%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="404.aspx.cs" Inherits="FCR2.abs" %>
Line 2: <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
Line 3: </asp:Content>
Source File: /404.aspx Line: 1 `enter code here`
This is my 404.aspx file:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="404.aspx.cs" Inherits="FCR2.abs" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Page Not Found</h1>
<p>You have come here by mistake or the page you are trying to view is no longer availible.</p>
<p>Go back to the Home Page</p>
</asp:Content>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
This is the 404.aspx.cs code:
namespace FCR2
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
This is the 404.aspx.designer.cs code:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace FCR2 {
public partial class abs {
}
}
Make sure you are using the same class names for that part of your code.
If you are using abs, you need to rename this like that:
namespace FCR2
{
public partial class abs : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {
}
}
}
Not sure as what you are trying over here
public partial class abs {
}
This is defined as partial class and is not inhesriting for Page (as it happens for WebForm1)
and your inherits points out to Inherits="FCR2.abs" which i believe should be WebForm1 instead of abs
Try right click Convert to Web Application and that should generate the proper designer file for you
A page could have an attribute MasterType to make Page.Master to be strong-typed:
<%# MasterType VirtualPath="~/Site.master" %>
If all my pages inherits specific class inherited System.Web.UI.Page itself, can I someway get access to this.Master property in it so I could call master page's methods?
In your base class that all pages inherit from, just override the Master property, something like this:
public new SiteMaster Master
{
get { return base.Master as SiteMaster ; }
}
or abatishchev's own variant:
public new ISiteMaster Master
{
get { return base.Master as ISiteMaster; }
}
I have the following types and classes:
namespace MVC.Models
public class Page
{
public EditableContent Content {get; set; }
}
public class EditableContent
{
public TemplateSection SidebarLeft {get; set; }
public TemplateSection SidebarRight {get; set; }
}
I want to edit the Page instance in my Edit.aspx View. Because EditableContent is also attached to other models, I have a PartialView called ContentEditor.ascx that is strongly typed and takes an instance of EditableContent and renders it.
The rendering part all works fine, but when I post - everything inside my ContentEditor is not binded - which means that Page.Content is null.
On the PartialView, I use strongly typed Html Helpers to do this:
<%= Html.HiddenFor(m => m.TemplateId) %>
But because the input elements on the form that are rendered by ContentEditor.ascx does not get the Content prefix to its id attribute - the values are not binded to Page.
I tried using loosely typed helpers to overcome this:
<%= Html.Hidden("Content.TemplateId", Model.TemplateId) %>
And when I'm dealing with a property that is a List<T> of something it gets very ugly. I then have to render collection indexes manually.
Should I put both Page and EditableContent as parameters to the controller action?:
public ActionResult Edit(Page page, EditableContent content) { ... }
What am I missing?
I would suggest you to use the EditorFor helper
Model:
public class EditableContent
{
public string SidebarLeft { get; set; }
public string SidebarRight { get; set; }
}
public class Page
{
public EditableContent Content { get; set; }
}
Views/Home/Index.aspx:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ToDD.Models.Page>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) { %>
<%--
This is the important part: It will look for
Views/Shared/EditorTemplates/EditableContent.ascx
and render it. You could also specify a prefix
--%>
<%= Html.EditorFor(page => page.Content, "Content") %>
<input type="submit" value="create" />
<% } %>
</asp:Content>
Views/Shared/EditorTemplates/EditableContent.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ToDD.Models.EditableContent>" %>
<%= Html.TextBoxFor(m => m.SidebarLeft) %>
<br/>
<%= Html.TextBoxFor(m => m.SidebarRight) %>
And finally Controller/HomeController:
public class HomeController : Controller
{
public ActionResult Edit()
{
var page = new Page
{
Content = new EditableContent
{
SidebarLeft = "left",
SidebarRight = "right"
}
};
return View(page);
}
[HttpPost]
public ActionResult Edit(Page page)
{
return View(page);
}
}