I'm currently on my first asp.net WebForms Site. To display different Sites I'm loading a control into a Placeholder in my masterpage.
example: UserControl uc = this.LoadControl("~/controls/home.ascx") as UserControl;
this goes over my default.aspx codebehind file. I'm now struggeling with fill in another control based on the URL. I know that you can get for example an ID (if my-domain.com/default.aspx?id=1 then show control blabla) but is it possible that I read out the URL and instead of the ID a string? for examples:
my-domain.com/home -> this goes over my default.aspx, but shows de home controller
my-domain.com/contact-> this goes over my default.aspx, but shows de contact controller
Can I check if it's "/home" and then show the home-control?
Has anyone an idea, how I could solve this problem?
Thanks guys :)
Here are a few code snippets:
masterpage.master:
<asp:ContentPlaceHolder id="content" runat="server"></asp:ContentPlaceHolder>
default.aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/masterpage.master" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="myproject._default" %>
default.aspx.cs:
public partial class _default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ContentPlaceHolder content = this.Master.FindControl("content") as ContentPlaceHolder;
displayControl(content);
}
private void displayControl(ContentPlaceHolder content)
{
UserControl uc = this.LoadControl("~/controls/home.ascx") as UserControl;
if ((content != null) && (uc != null))
{
content.Controls.Add(uc);
}
}
}
home.ascx:
my HTML-Page
My folders are in the following structure:
css
img
javascript
App_Data
bin
obj
controls
home.aspx
contact.aspx ... etc.
default.aspx (with the code behind file .cs)
masterpage.master
misc: web.config and other files and folders...
If you want your site to go from domain.com/default.aspx?id=1 to domain.com/home, or domain.com/login you need to enable Friendly URLs and setup a route in your WebForms.
Scott Hanselman has a walk-through at the following link...
http://www.hanselman.com/blog/IntroducingASPNETFriendlyUrlsCleanerURLsEasierRoutingAndMobileViewsForASPNETWebForms.aspx
Related
Need to setup a URL for data to be sent, as seen below.
http://yourdomain/getdelivery.aspx?batchid=$batchid&mobile=$mobile&status=$status
Hello,
I googled but almost all the results were how to get the data and not how to set up the web page and set the domain. Me being a newbie both as a sysadmin and certainly with web development I got stuck. I ask for your help to set me in the correct course.
Best Regards,
The simpliest way is to add a web form page called GetDelivery.aspx.
In GetDelivery.aspx :
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="GetDelivery.aspx.cs" Inherits="PortalBmoTrsb.GetDelivery" %>
In GetDelivery.aspx.cs :
namespace MyNameSpace
{
public partial class GetDelivery : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var batchid = Request["batchid"];
var mobile = Request["mobile"];
var status = Request["status"];
}
}
}
You also should check a look to Web Api Controller.
I'm creating a website which allows users to log in. After logging in successfully, user's name should be displayed across each page, for example, at the top right corner. I have a ContentPlaceHolder on Master Page. An h3 tag would then be created and added into this ContentPlaceHolder.
Master Page:
<asp:ContentPlaceHolder runat="server" ID="UserNamePlaceHolder">
</asp:ContentPlaceHolder>
Login Page:
<%# MasterType VirtualPath="~/Master" %>
Login Class:
protected void Login_LoggedIn(object sender, EventArgs e)
{
ContentPlaceHolder userNamePlaceHolder =
(ContentPlaceHolder)Master.FindControl("UserNamePlaceHolder");
var h3 = new HtmlGenericControl("h3");
h3.InnerHtml = login.UserName;
userNamePlaceHolder.Controls.Add(h3);
}
I did debugging step by step. Nothing went wrong: no null or empty value, each variable was created. However, the user name was not displayed at all. Does anyone have an idea?
A cleaner and better approach would be to create a public property on the Master page:
public string UserName
{
get
{
return Literal1.Text;
}
set
{
Literal1.Text = value;
}
}
That's it place the literal with ID Literal1 anywhere you want on the master page:
<asp:Literal runat="server" ID="Literal1" />
You are already adding Master directive for strongly typing Master class, so now your login class would look like this:
protected void Login_LoggedIn(object sender, EventArgs e)
{
Master.UserName = login.UserName;
userNamePlaceHolder.Controls.Add(h3);
}
Hope this helps.
I am using nested master pages where i want to use Label control from nested master page and update its text. but it is not accessing. When i removed outer master page then it is working fine. Following is the markup and code.
OUTER MASTER
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Roster.Site" %>
NESTED MASTER
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="RoasterMaster.master.cs" Inherits="Roster.RoasterMaster" MasterPageFile="~/Site.Master" %>
<%# MasterType VirtualPath ="~/Site.Master" %>
CONTENT PAGE
<%# Page Language="C#" AutoEventWireup="true" Inherits="RequestsView" CodeBehind="ViewRequestsByPM.aspx.cs" MasterPageFile ="~/Roaster/RoasterMaster.Master" Title ="Roaster- View Requests by PM" %>
<%# MasterType VirtualPath ="~/Roaster/RoasterMaster.Master" %>
CONTENT PAGE CODE
protected void Page_Load(object sender, EventArgs e)
{
Label lblTitle = new Label();
lblTitle =(Label)Master.FindControl("lblTitle");
lblTitle.Text = "View Roaster Request";
}
What is going wrong with the implementation. Please help. Thanks
You can add the below code snippet in
NESTED MASTER PAGE
public string PageTitle { get; set; } // In page_load
lblTitle.Text = PageTitle;
CONTENT PAGE CODE
this.Master.PageTitle = "YOUR TEXT";
This will work for you...
Assuming that your label is in Roster master page, you can simply add method to set the text in master page code behind. For example,
in RoasterMaster.master.cs
public void SetTitle(string value)
{
this.lblTitle = value;
}
And in content page code
Master.SetTitle("View Roaster Request");
In case, your label is in outer master then you can similarly forward the call to the outer master from roster master code.
EDIT
Your code does not work in nested master case scenarios because Master page contents get added within page control hierarchy with different naming container. FindControl method does not span multiple naming containers which is the case here - because of nesting you have nested naming containers. Page.Master would give you outer naming container but your label might be lying in inner naming container. One of the way, is to write your own find control implementation that will recurs within the control tree but really it does not make sense - I would rather use above code which is more efficient and more importantly better maintainable.
Im working on an e-commerce platform which supports multiple stores on different domains. The backend is complete (for now) and I'm now starting the front-end part. Since the platform supports multiple stores I need some kind of templating system and I haven't quite figured out what's the best way to do this.
This are my requirements:
I don't want to rebuild my solution to add a new template
Templates are stored in /Templates/TemplateDirectoryName
I want to be able to use (predefined) usercontrols inside the templates.
I use URL routing and only have 1 Default.aspx page which controls which page template and additional code needs to be loaded.
This is what I came up with so far:
In my template directory i have templates created with master pages (A homepage master file, a default master file, and sub-master files referencing the default master file...for product detail, browse, search etc)
My Default.aspx page picks the right template based on routing values
While this way works I don't think it's very practical but the more I think about it the more I come to the conclusion that there are not so many other options to go around this. I think this is what I want to ask: Is there a way to use usercontrols in a template and have the template completely seperated from the application so users can create templates without having to worry about the site's namespace and structure?
Kind regards,
Mark
Since you are referencing a folder for templates, wouldn't it be possible to just change the .aspx files in the folder and asp.net shall pick up the template based on the url path that you've mentioned? I think that is possible in asp.net.
Also, Frameworks like DotNetNuke, Sharepoint, Joomla etc. have the similar concept. You can avail their features.
My proposed solution is below. It has a few constraints, like all master pages need to implement the same set of placeholder controls (not surprising). Take a look and let me know what you think.
I setup my folder structure like this:
Website -> Templates -> TemplateFolder (named same as the template)
Website -> Templates -> UserControls (User controls are stored in a non-template specific folder)
I defined a simple Template configuration class which we can store/save/load a basic template deffinition:
public class Template
{
public string TemplateName { get; set; }
public string UserControlName { get; set; }
public string MasterPageName { get; set; }
public string TemplateFolder
{
get
{
return GetTemplateFolder(TemplateName);
}
}
public string TemplateConfigFile { get { return GetTemplateConfigFile(TemplateName); } }
private static string GetTemplateFolder(string name)
{
return HttpContext.Current.Server.MapPath("~/Templates/" + name + "/");
}
private static string GetTemplateConfigFile(string name)
{
return GetTemplateFolder(name) + "/" + name + ".config";
}
public Template()
{
}
public void Save()
{
XmlSerializer xs = new XmlSerializer(typeof(Template));
if (!Directory.Exists(TemplateFolder)) Directory.CreateDirectory(TemplateFolder);
using (FileStream fs = File.OpenWrite(TemplateConfigFile))
{
xs.Serialize(fs, this);
}
}
public static Template Load(string name)
{
if(!File.Exists(GetTemplateConfigFile(name))) return null;
XmlSerializer xs = new XmlSerializer(typeof(Template));
using (FileStream fs = File.OpenRead(GetTemplateConfigFile(name)))
{
Template t = (Template)xs.Deserialize(fs);
return t;
}
}
}
You can build some bare xml code to get started with by running the code below:
Template t1 = new Template() { TemplateName = "Template1", MasterPageName = "Child1.master", UserControlName = "uc1.ascx" };
Template t2 = new Template() { TemplateName = "Template2", MasterPageName = "Child2.master", UserControlName = "uc2.ascx" };
t1.Save();
t2.Save();
I created a basic master page. This page will probably never be used except to give your default page the basic placeholders. All of your master pages should have the same set of placeholders as your base one so that your pages can use them all interchangably. Notice I left a placeholder for our user control.
<%# Master Language="C#" AutoEventWireup="true" CodeFile="BaseMaster.master.cs" Inherits="Templates_Masters_BaseMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="cphHeader" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder id="cpUserControl" runat="server">
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder id="cphFooter" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Now I create a basic aspx web page that uses the above master page.
<%# Page Title="" Language="C#" MasterPageFile="~/Templates/Masters/BaseMaster.master" AutoEventWireup="true" CodeFile="DefaultTemplated.aspx.cs" Inherits="DefaultTemplated" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="cphHeader" Runat="Server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="cpUserControl" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="cphFooter" Runat="Server">
</asp:Content>
In the codebehind we'll setup the basic templating. This sets the masterpage and adds a pre-defined user control to the content placeholder for user controls. If you wanted you could just make a panel or something and add it to that fixed control, but I thought you might appreciate seeing how to make it work with masterpages.
public partial class DefaultTemplated : System.Web.UI.Page
{
private Template PageTemplate
{
get
{
if (_tLoaded == null)
{
string template = Request.QueryString["template"];
if (string.IsNullOrEmpty(template)) return null;
Template t = Template.Load(template);
_tLoaded = t;
}
return _tLoaded;
}
}
private Template _tLoaded = null;
protected void Page_Load(object sender, EventArgs e)
{
if (PageTemplate != null)
{
//cpUserControl is the name of my usercontrol placeholder
((ContentPlaceHolder)Page.Form.FindControl("cpUserControl")).Controls.Add(
Page.LoadControl("~/Templates/UserControls/" + PageTemplate.UserControlName));
}
}
protected void Page_PreInit(object sender, EventArgs e)
{
if (PageTemplate == null) return;
this.MasterPageFile = "~/Templates/" + PageTemplate.TemplateName + "/" + PageTemplate.MasterPageName;
}
}
If you had a template named "Template1" you could use it by calling "Default.aspx?template=Template1". Since you are using URL rewriting you would use the rewriting to pass the template name as a parameter to the page.
Another option that could be combined with the above would be the use of Page.ParseControl. Using this you could store your raw asp.net designer code (designer only) in a database or raw text file. Then you could instantiate it load it like this:
//where pnl1 is a Panel on the page. Page.ParseControl just returns a control object, so use it anywhere.
pnl1.Controls.Add(Page.ParseControl("raw asp.net designer code here."));
One great thing about this is that nested controls work great too.
I don't know if I understand correctly:
If you don't want to rebuild, then I can tell a CMS concept is best suitable for you.
You can store your templates as an HTML in database and from DB you can fetch it back,
You can give an admin functionality with editor to edit your template online also.
I'm embarrassed to ask this here because it's clearly been duplicated several times already on StackOverflow. I've read a lot of stuff including:
http://msdn.microsoft.com/en-us/library/xxwa0ff0
http://msdn.microsoft.com/en-us/library/c8y19k6h.aspx
http://www.velocityreviews.com/forums/t110056-cannot-access-strongly-typed-properties-in-master-page.html
I think I've done exactly what those article say, but it's not working for me.
Here's the top of my master page, named "MasterNoNews.master":
<%# Master Language="C#" %>
<%# Import Namespace="MyMediHealth.DataAccess" %>
<%# Import Namespace="MyMediHealth.DataAccess.Containers" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public virtual UserContainer CurrentUser;
protected void Page_Load(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
CurrentUser = new MembershipQueries().getUserFromUserIdName(Page.User.Identity.Name);
}
</script>
Here's the top of my child page, named "MyProfile.aspx":
<%# Page Title="" Language="C#" MasterPageFile="~/MasterNoNews.master"
AutoEventWireup="true" CodeBehind="MyProfile.aspx.cs"
Inherits="MyMediHealth.Interface.MyProfile" %>
<%# MasterType VirtualPath="~/MasterNoNews.master" %>
Here's the code-behind on my child page, named "MyProfile.aspx.cs" that's not working:
using System;
using System.Web.UI;
using MyMediHealth.DataAccess.Containers;
using MyMediHealth.DataAccess;
namespace MyMediHealth.Interface
{
public partial class MyProfile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// doesn't work
UserContainer user = Master.CurrentUser;
// also doesn't work
UserContainer user = ((MasterNoNews)this.Master).CurrentUser
}
}
}
In the first case, VS is telling me System.Web.Ui.MasterPage does not contain a definition for CurrentUser. In the second case, VS says the type or namespace 'MasterNoNews' could not be found.
What am I doing wrong?
You'll probably still need to move the master page's code to the code behind, but if you put this,
<%# MasterType VirtualPath="~/MasterPages/Site.master" %>
on the aspx page you'll be able to access the master page's public methods directly without all that casting. Like so:
UserContainer user = Page.Master.CurrentUser
If you're using the master page's code from loads of child pages then I'd create an interface and have the master page implement it.
This will not work because you have created properties within Master page (and not code-behind). Typically, master page code would get compiled dynamically and a class name (depending on file name) will be created in a temporary assembly. As you are not reffering to this generated class name within temp assembly, you get error. Correct way will be to have code behind file for the master. For example, master will be
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="MasterNoNews.master.cs" Inherits="[Your Namespace].MasterNoNews" %>
And in code-behind file (MasterNoNews.master.cs) have your properties:
namespace [Your Namespace]
{
public partial class MasterNoNews : System.Web.UI.MasterPage
{
public virtual UserContainer CurrentUser;
protected void Page_Load(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
CurrentUser = new MembershipQueries().getUserFromUserIdName(Page.User.Identity.Name);
}
}
}
Now the second syntax would work i.e.
UserContainer user = (([Your Namespace].MasterNoNews)this.Master).CurrentUser