I'm creating a content management system where a user can select a css file from their server and the application will parse and store the css. The application will need to be able to parse the css classes out, record them, and store the css content to be dynamically added to another page where a user can select the different css classes from a drop down. So does anyone know of a way to add css content to a page dynamically, for example from a database? I've found a few projects for parsing the css, here .
Thanks in advance.
Make a controller which serves the CSS content:
<link rel="stylesheet" href="#Url.Action("GetCss", "Serve", new {id="filename"})" />
Controller code:
public class ServeController: Controller
{
public ContentResult GetCss(string id)
{
string cssBody = GetCssBodyFromDatabase(id);
return Content(cssBody, "text/css");
}
}
A good approach for a WebForms-only project is to link to an .ashx handler in your page instead of a static CSS file:
<link rel="stylesheet" type="text/css" href="DynamicStyles.ashx" />
Then create the handler (add a 'Generic Handler' item from Visual Studio) and within it you can load the CSS from a database or wherever. Just make sure you set the content type correctly in the handler, so that browsers recognise the response as a valid stylesheet:
context.Response.ContentType = "text/css";
I think NullReference gave you a MVC solution because you tagged your post "mvc". If you're using ASP.NET Web forms, you can use the same technique used when generating CSS-links on-the-fly on user-controls. On the page's Page_Init event, do something like the following (in the example below, I'm linking to jquery-ui-CSS):
protected void Page_Init(object sender, EventArgs e)
{
System.Web.UI.HtmlControls.HtmlLink jqueryUICSS;
jqueryUICSS = new System.Web.UI.HtmlControls.HtmlLink();
jqueryUICSS.Href = "styles/jquery-ui-1.8.13.custom.css");
jqueryUICSS.Attributes.Add("rel", "stylesheet");
jqueryUICSS.Attributes.Add("type", "text/css");
Page.Header.Controls.Add(jqueryUICSS);
}
If you want actual elements to be rendered on the header, then use HtmlGeneric control instead of HtmlLink in my example above. It's still the same technique--on Page_Init, add to the Page.Header.Controls collection:
protected void Page_Init(object sender, EventArgs e)
{
System.Web.UI.HtmlControls.HtmlGenericControl mystyles;
mystyles = new System.Web.UI.HtmlControls.HtmlGenericControl();
mystyles.TagName = "style";
string sampleCSS = "body { color: Black; } h1 {font-weight: bold;}";
mystyles.InnerText = sampleCSS;
Page.Header.Controls.Add(mystyles);
}
Related
Is it possible to add <!DOCTYPE HTML> to an aspx page from the code behind file of a ascx page?
Adding doctype to the master page is not an option because it'll wreck the rest of our sharepoint sites.
I've tried to override the render method:
protected override void Render(HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder("<!DOCTYPE HTML>");
HtmlTextWriter textWriter = new HtmlTextWriter(new System.IO.StringWriter(sb));
//base.Render(writer);
base.Render(textWriter);
writer.Write(sb.ToString());
}
but apparently it doesn't help.
For me it worked this way:
First I added a literal on top of the page, first line, outside the <Form runat="server":
<asp:Literal runat="server" ID="litHTMLSchema"></asp:Literal>
Then from code-behind:
// HTML 5
litHTMLSchema.Text = #"<!DOCTYPE html>" + Environment.NewLine + #"<html>";
I don't think this is the best approach, but it works without any issues.
Since you are using sharepoint, you could create a custom webcontrol in code in a WSP Package Farm Solution.
Create a class Called DynamicDocTypeControl
public class DynamicDocTypeControl : System.Web.UI.WebControl *(check namespace for typos)
{
override Render(...) {
//add some conditional logic here for your dynamicness...
writer.Write("<!DOCTYPE HTML>");
}
}
Add an empty sharepoint element to your project and go to the properties window and use the safe control section in the property window to register your control as a safe control.
Build/Package the wsp and deploy it to the farm.
Then edit your master page in sharepoint designer and drop your control on it where the doctype should be rendered.
Putting it in the master page won't wreck your sites because you can make your render logic not render anything if it's not on an allowed page.
Just have some code on your aspx page that sets an HttpContext.Current.Item... value that the doctype control looks for to determine if it should render. As long as your aspx page sets the config flag before Render is called it will be there when render fires on the doc type control.
e.g.
<# Register TagPrefix="XYZ" Namespace="XYZ.Controls" Assembly="XYZ... (include fully qualified assembly name)" />
<XYZ:DynamicDocTypeControl />
I have a content page connected to a master page. I can access an element on the master page and modify it directly from the content page .cs file by calling a method on the site master. (this is probably the most standard bug people have in this type of area)
My problem is that I wanted to extend this functionality to update the site master page from an AJAX request as well. The ajax file calls a different page which in turns starts an instance of the logic layer which I use for all the calculations and connections. What I am trying to do is access the sitemaster directly from the logic layer (only a .cs file).
My current code is this:
SiteMaster sm = new SiteMaster();
sm.MyMethod("param1", "param2");
This successfully accesses the method called "MyMethod" in the site master but inside this method I have this code:
mySpan.InnerText = "this is a test";
which doesn't work because I get the "Object refernce not set to an instance of an object...." error. This is because mySpan is NULL. If I call it using this.mySpan.InnerText though, if I hover over "this" then I can see the ID "mySpan".
Does anyone know how I can get around this problem? Every search I have made is regarding people who want to access the elements from the content page which already works for me.
I believe you've got a misunderstanding here. If I understand correctly you've got a page with a MasterPage. On that aspx page you're doing an ajax call (perhaps to a WebService) which does something like:
[WebMethod]
public void UpdateText(string message)
{
var master = new SiteMaster();
master.mySpan.Text = message;
}
There are a couple of things wrong here.
When you use this approach is an aspx page you're updating that Page's master. For example:
public void OnSomeRandomButtonClick(object sender, EventArgs e)
{
((SiteMaster)this.Page.Master).mySpan.Text = "Some Text";
}
What you're doing here is updating the span on the master page before it's being sent to your browser. The other subtly is that you're not creating a new SiteMaster, you're using the Page's existing Master and casting it to a SiteMaster.
There are a couple of reasons you can't do this with ajax:
A webservice doesn't have a MasterPage
By the time you send an ajax request your Master page has already been created and sent to the browser.
So your question becomes how do we update a span in the Master without posting back to the server?
Lets look at the html which is actually on your box, it will look something like this:
<html>
<head>
<title>My Awesome Page</title>
</head>
<body>
<h1>This is my Awesome Website</h1>
<span id="mySpan">I'm sure you'll like it</span>
<div>
<p>Page Content</p>
<div>
</body>
</html>
Lets assume that everything here is generated by the master and only the <p>Page Content</p> is your aspx page (There will also be loads of ASP.NET junk added, we'll ignore that for the time being).
What you want to do is update the text in mySpan without posting back to the server. You can do this via the javascript - don't get ajax involved at all!
I'm going to assume you're using jQuery (mostly because I'm more familiar with it that plain old JS). You've got the ID of your span ("mySpan") so the rest is easy:
$('#mySpan').html('This is the updated message');
You can put this in either a click or a page load.
No. You can not simply construct an ASP.NET page and use its state.
ASP.NET pages (and controls and Master pages) are being constructed and initialized from inside the ASP.NET engine based on the Markup provided for them. There is for example no initialization for mySpan inside the codeBehind of your master page, that will be constructed when the code generated based on the Markup is invoked based on a user request.
So you define this in your class:
protected HtmlGenericControl mySpan;
But the ASP.NET engine will compile this markup
<span id="mySpan" style="color:green"></span>
to this code:
this.mySpan = new HtmlGenericControl();
this.mySpan.Style.Add("color", "green);
and that is why you can use this object inside your code.
So if you want to use a property of your Master page from your Business layer, you have so many choices. On of the fastest one to implement is to make your Logic class singleton inside the Session scope, store the value you want to use inside the master page into that singleton object and then read that value from the master Page. This is an example of what you should do, of course it is rough.
class Logic
{
public static Logic Instance
{
get
{
if (HttpContext.Current.Session["LogicInstance"] == null)
HttpContext.Current.Session["LogicInstance"] = new Logic();
return (Logic) HttpContext.Current.Session["LogicInstance"];
}
}
public string TextForSpan {get;}
// The rest of your implementation
}
Instead of the code to assign the inner text, write:
Logic.Instance.TextForSpan = "This is my text";
And inside your master page:
this.mySpan.InnerText = Logic.Instance.TextForSpan;
I have a user control which requires Javascript/Jquery per control. It is actually a control to represent data graphically using some javascript library. As a norm all my javascript links are located at the bottom of the page in the Master Page. This implies I cannot write any javascript in the control because it will appear before any of its dependencies. Also, Even if the script is located at the bottom of the page, it only works for the first control. Has anyone encountered similar challenges? I'm looking for a way out. Thanks
You can register client scripts from code-behind.
var clientScriptManager = Page.ClientScript;
if(!clientScriptManager.IsStartupScriptRegistered("a_key")) { //If multiple control instances are present on the page, register scripts only once
RegisterStartupScript(Page.GetType(), "a_key", "<script src=\"/js/a_library.js\"></script>"));
}
RegisterStartupScript will add <script> tag at the very bottom of the page, before </body> closing tag.
I had a similar issue "updating" a legacy site that had tons of inline JS... so I also ran into issues when I moved jQuery and other scripts to the bottom of the page. I solved it by adding a new ContentPlaceHolder to the master page, underneath the other script references:
<asp:ContentPlaceHolder ID="ScriptsPlace" runat="server"></asp:ContentPlaceHolder>
</body>
Then went through the pages and moved all the inline JS into a content block for ScriptsPlace.
<asp:Content ID="Content5" ContentPlaceHolderID="ScriptsPlace" runat="server">
<script>
//some awesome JS
</script>
</asp:Content>
Although this doesn't work for user controls... so I made a somewhat hacky solution that essentially involved putting all of the user controls JS into a div named _jsDiv and then from the code-behind moving that div into the placeholder (I'm not fond of RegisterStartupScript and it's not practical for a lot of code).
Since I did this in multiple controls, I did these steps:
Step 1 - Make a custom user control, ScriptMoverUserControl.cs:
public class ScriptMoverUserControl : System.Web.UI.UserControl
{
protected void Page_PreRender(object sender, EventArgs e)
{
ContentPlaceHolder c = Page.Master.FindControl("ScriptsPlace") as ContentPlaceHolder;
HtmlGenericControl jsDiv = this.FindControl("_jsDiv") as HtmlGenericControl;
if (c != null && jsDiv != null)
{
jsDiv.ID = Guid.NewGuid().ToString(); //change the ID to avoid ID conflicts if more than one control on page is using this.
c.Controls.Add(jsDiv);
}
}
}
Step 2 - Make your user control use this new control class:
It will inherit ScriptMoverUserControl instead of System.Web.UI.UserControl
public partial class SomeGreatControl : ScriptMoverUserControl
Step 3 - Dump your user control scripts in a div named _jsDiv:
<div id="_jsDiv" runat="server">
<script>
//some awesome JS
</script>
</div>
It's been working fine for me, but if anyone knows a better/cleaner way, I'd like to know!
I have access to a server with aspx pages. I need to add a title, parapgraphs, etc to a page. The page currently only has the following line:
<%# Page Language="C#" AutoEventWireup="true" Inherits="Access.Login" %>
I do not have access to the CS files, just the DLL. Anyway, when I try to add any html to the document nothing changes. I am able to change the CSS, and if I remove the "inherits" then whatever HTML I have gets displayed, but when the "inherits" is there only the default page gets displayed and none of my additions.
Admittedly I am new to ASP and moreover I am not trying to become a guru just to add some HTML to a page, but any advice would be great, thanks!
Try putting your Page_Load embedded in the .aspx and add controls that way:
<%# Page Language="C#" AutoEventWireup="true" Inherits="Access.Login" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e) {
if (!Page.IsPostBack) {
Controls.Add(whatever);
}
}
</script>
<!-- Try this if the above does not work -->
<script runat="server">
new protected void Page_Load(object sender, EventArgs e) {
base.Page_Load(sender, e);
if (!Page.IsPostBack) {
Controls.Add(whatever);
}
}
</script>
Fundamentally, I'm afraid this is not possible. .NET is a single-inheritance language/framework. So when it says Inherits="Access.Login" that means you can only have it use Access.Login OR your code-behind, but not both.
That said, you could jump through some crazy hoops to accomplish your goal. Like create a brand new "wrapper" page, then in the code-behind fire off an http request to the page you want. Load the response, which will just be a really long string into a 3rd-party DOM parser, or if you're confident you're getting 100% valid XML back, use .NET's built-in XmlDocument or XDocument to parse the page, find your html elements, make your changes, then do a Response.Write with your modified content.
And that's a real-life example of going around your elbow to get to your...
I am not 100% certain this will work, but you could have a code-behind file inherit from Access.Login and use the new (override will not work if Page_Load isn't marked as virtual) keyword with Page_Load. Then you could use Inherits="YourAssembly.NewLogin".
The part I am not sure about is whether or not asp.net uses the page class or your subclass to call the Page_Load method. If page_Load was virtual, it wouldn't matter, but since it isn't the new will only be called if the page is cast into your subclass. It is worth a try though.
I would like to dynamically add a html to a server control and then I want to have access to each control from this html. If I use the inner html property of a control I can notice the html was added as a literalControl and I would like it to be a html control with some other html controls
ex:
//aspx file
<div id="content" runat="server"><div>
//aspx.cs file
protected void Page_Load(object sender, EventArgs e)
{
content.AddControlsFromHtml("<input type='text' id='textBox' />")
}
//get the control
((HtmlInputText)content.FindControl("textBox")).Value = "hello"
Is this possible?
I need this behaviour to create different layouts for a page
for creating dynamic html, put your code in page_init event..