Reusing ASP.NET code in multiple pages - asp.net

Is there a way to reuse a piece of ASP.NET code (that tag-based code, not the code-behind) in many different pages? For example I have a <div> with some contents in it that appears in 5 different pages of my site. I'm looking for a technique through which I could save this <div> in a separate web-content file so to speak, with maybe a different extension like MyDiv.ASPC and could then do a server-side tag anywhere in a webpage like:
<asp:Import href="~/MyDiv.aspc" />
and ASP.NET would inject the entire content of this file at that point where this tag appears.
I thought of creating a user control for this, but I'm not sure if a user control always injects precisely what is written in its body, or could there sometimes be unwanted tags generated by user control itself.
Or are there existing better ways of doing this?
Edit
About Master Pages, they are far away from what I'm looking for. They are actually good for a common basic layout of your website. My idea is quite opposite of that. My pages do not have a common layout; it is just that they have one common <div>. It is more closely fulfilled by a UserControl.
For UCs, my fear is that they generate more than what is written in their body, whereas what I'm after is a simple text injection. To put it technically, what I'm looking for is basically a preprocessor step (kind of #include thing in C++) rather than a compiler step, if you see what I mean.

You need to use ASP.NET User Controls, as these are specifically created to be the solution to the problem you are describing. For more information, see MS Documentation.
From their documentation...
In addition to using Web server controls in your ASP.NET Web pages,
you can create your own custom, reusable controls using the same
techniques you use for creating ASP.NET Web pages. These controls are
called user controls.
A user control is a kind of composite control that works much like an
ASP.NET Web page—you can add existing Web server controls and markup
to a user control, and define properties and methods for the control.
You can then embed them in ASP.NET Web pages, where they act as a
unit.

An empty userControl would do just that - nothing. A user Control just adds it's contents to the page, or usercontrol hosting it. It adds nothing extra.
UserControls give you a nice easy page fragment type approach to reusing content. They work great within a project & most people use them for just that.
If you wanted to make something more reusable across projects, you could write server control. It's more involved, but much more reusable. Google should be able to find you many tutorials on how to do this.

Ran a short test. User Controls do not enter extra tags as long as you don't place any Runat="Server" tags in it, so this would indeed be a solution I guess.
You can also read output from a cache object where you would read your files.
So
<%= Static.ContentXyz %>
would mean:
public static class Static
{
public static string ContentXyz
{
get
{
string s;
if (!this.cacheDictionary.TryGetValue("ContentXyz", out s))
{
s = File.ReadAllText(Server.MapPath("ContentXyz.html"));
this.cacheDictionary("ContentXyz", s);
}
return s;
}
}
}

Related

Get value form elements inside div with only ASP.NET

I'm newbie in ASP.NET and i think that my question is quite simple, but I'm not getting success in my searches through google or even stackoverflow.
I have a asp.net method (vb.net) that loads a entire html page inside a div.
Doing searches, i discovered that it can be like this:
On .aspx page:
<div id="content"></div>
On .vb codebehind:
Private sub LoadContent()
content.InnerHtml = MyDLL.LoadFromDatabase.Value.ToString()
End Sub
So, nothing special until here.
But, if consider that the html code loaded from database has form elements like <input id="name" type="text">, my problem starts...
On page postback these don't keep the values as <asp:TextBox> created natively on code, does.
And the other thing that I want is a way to retrieve the value from them to work on codebehind, like: myvar = content.Controls("name").Value
At least, is there a way to solve my problem?
Sorry for my bad english, and thanks so much.
CRice is right. If you want the viewstate to persist through postback you need to create the controls server-side.
Careful though: I've had bad experience with dynamically created controls on Asp.Net, specifically when trying to bind events to them. Not only would you have to use delegates and events (a hard topic for a newbie), also when I tried it a few years ago I just couldn't get it to work, no matter what.
If you're going for dynamic created controls, make sure it's worth the effort, because it WILL be an effort, now and in the future when you would like to maintain and add expand. A rule of thumb is that dynamic mechanisms are always harder to maintain than static ones, but they provide more flexibility.
Having that said, if you're still going for dynamic html loading, be aware that better solutions exist, though they require different architectures: client side frameworks (best is angluar.js) provide dynamic loading of "modules" (and much more), which is what you want. On the server side, asp.net MVC with its Razor view engine, partial views etc., is better suited for dynamic html generation.
Back to your original question,are you sure you need a full postback? What about a nice neat Ajax call to a web service? Can get the job done in many cases without reloading the whole page. I guess using jquery's $.ajax syntax and creating a simple .asmx web service will be easiest for you.
Last but not least, why use vb.net instead of c#? It sucks man. Give it up while you still can.

ASP.NET - Parse / Query HTML Before Transmission and Insert CSS Class References

As a web developer I feel too much of my time is spent on CSS. I am trying to come up with a solution where I can write re-usable CSS i.e. classes and reference these classes in the HTML without additional code in ASPX or ASCX files etc. or code-behind files. I want an intermediary which links up HTML elements with CSS classes.
What I want to achieve:
Modify HTML immediately before transmission
Select elements in the HTML
Based on rules defined elsewhere (e.g. in a text file relating to
the page currently being processed):
Add a CSS class reference to multiple HTML elements
Add multiple CSS class references to a single HTML element
How I envisage this working:
Extend ASP.NET functions which generate final HTML
Grab all the HTML as a string
Pass the string into a contructor for an object with querying (e.g. XPATH) methods
Go through list of global rules e.g. for child ul of first div then class = "navigation"
Go through list of page specific rules e.g. for child ul of first div then class &= " home"
Get processed HTML from object e.g. obj.ToString
ASP.NET to resume page generation using processed HTML
So what I need to know is:
Where / how can I extend ASP.NET page generation functions (to get all HTML of page)
What classes have element / node querying methods and access to attributes
Thanks for your help in advance.
P.S. I am developing ASP.NET web forms websites with VB.net code-behinds running on ISS 7
Check out my CsQuery project: https://github.com/jamietre/csquery or on nuget as "CsQuery".
This is a C# (.NET 4) port of jQuery. In basic performance tests (included in the project test suite) selectors are about 100 times faster than HTML Agility Pack + Fizzler (a css selector add-on for HAP); it's plenty fast for manipulating the output stream in real time on a typical web site. If you are amazon.com or something, of course, YMMV.
My initial purpose in developing this was to manipulate HTML from a content management system. Once I had it up and running, I found that using CSS selectors and the jQuery API is a whole lot more fun than using web controls and started using it as a primary HTML manipulation tool for server-rendered pages, and built it out to cover pretty much all of CSS, jQuery and the browser DOM. I haven't touched a web control since.
To intercept HTML in webforms with CsQuery you do this in the page codebehind:
using CsQuery;
using CsQuery.Web;
protected override void Render(HtmlTextWriter writer)
{
var csqContext = WebForms.CreateFromRender(Page, base.Render, writer);
// CQ object is like a jQuery object. The "Dom" property of the context
// returned above represents the output of this page.
CQ doc = csqContext.Dom;
doc["li > a"].AddClass("foo");
// write it
csqContext.Render();
}
To do the same thing in ASP.NET MVC please see this blog post describing that.
There is basic documentation for CsQuery on GitHub. Apart from getting HTML in and out, it works pretty much like jQuery. The WebForms object above is just to help you handle interacting with the HtmlTextWriter object and the Render method. The general-purpose usage is very simple:
var doc = CQ.Create(htmlString);
// or (useful for scraping and testing)
var doc = CQ.CreateFromUrl(url);
// do stuff with doc, a CQ object that acts like a jQuery object
doc["table tr:first"].Append("<td>A new cell</td>");
Additonally, pretty much the entire browser DOM is available using the same methods you use
in a browser. The indexer [0] returns the first element in the selection set like jquery; if you are used to write javascript to manipulate HTML it should be very familiar.
// "Select" method is the same as the property indexer [] we used above.
// I go back and forth between them to emphasise their interchangeability.
var element = dom.Select("div > input[type=checkbox]:first-child")[0];
a.Checked=true;
Of course in C# you have a wealth of other general-purpose tools like LINQ at your disposal. Alternatively:
var element = dom["div > input[type=checkbox]:first-child"].Single();
a.Checked=true;
When you're done manipulating the document, you'll probably want to get the HTML out:
string html = doc.Render();
That's all there is to it. There are a vast number of methods on the CQ object, covering all the jQuery DOM manipulation techniques. There are also utility methods for handling JSON, and it has extensive support for dynamic and anonymous types to make passing data structures (e.g. a set of CSS classes) as easy as possible -- much like jQuery.
Some More Advanced Stuff
I don't recommend doing this unless you are familiar with lower-level tinkering with asp.net's http workflow. There's nothing at all undoable but there will be a learning curve if you've never heard of an HttpHandler.
If you want to skip the WebForms engine altogether, you can create an IHttpHandler that automatically parses HTML files. This would definitely perform better than overlaying on a the ASPX engine -- who knows, maybe even faster than doing a similar amount of server-side processing with web controls. You can then then register your handler using web.config for specific extensions (like htm and html).
Yet another way to automatically intercept is with routing. You can use the MVC routing library in a webforms app with no trouble, here's one description of how to do this. Then you can create a route that matches whatever pattern you want (again, perhaps *.html) and pass handling off to a custom IHttpHandler or class. In this case, you're doing everything: you will need to look at the path, load the file from the file system, parse it with CsQuery, and stream the response.
Using either mechanism, you'll need a way to tell your project what code to run for each page, of course. That is, just because you've created a nifty HTML parser, how do you then tell it to run the correct "code behind" for that page?
MVC does this by just locating a controller with the name of "PageNameController.cs" and calling a method that matches the name of the parameter. You could do whatever you want; e.g. you could add an element:
<script type="controller" src="MyPageController"></script>
Your generic handler code could look for such an element, and then use reflection to locate the correct named class & method to call. This is pretty involved, and beyond the scope of this answer; but if you're looking to build a whole new framework or something this is how you would go about it.
Intercepting the content of the page prior to it being sent is rather simple. I did this a while back on a project that compressed content on the fly: http://optimizerprime.codeplex.com/ (It's ugly, but it did its job and you might be able to salvage some of the code). Anyway, what you want to do is the following:
1) Create a Stream object that saves the content of the page until Flush is called. For instance I used this in my compression project: http://optimizerprime.codeplex.com/SourceControl/changeset/view/83171#1795869 Like I said before, it's not pretty. But my point being you'll need to create your own Stream class that will do what you want (in this case give you the string output of the page, parse/modify the string, and then output it to the user).
2) Assign the page's filter object to it. (Page.Response.Filter) Note that you need to do it rather early on so you can catch all of the content. I did this with a HTTP Module that ran on the PreRequestHandlerExecute event. But if you did something like this:
protected override void OnPreInit(EventArgs e)
{
this.Response.Filter = new MyStream();
base.OnPreInit(e);
}
That would also most likely work.
3) You should be able to use something like Html Agility Pack to parse the HTML and modify it from there.
That to me seems like the easiest approach.

why not user control?

why should be used use control template in asp.net? please, someone say me.
Can anyone tell me why I should use a Control Template over a UserControl in ASP.Net?
If you're familiar with MVC, a User Control is like the WebForms equivalent of a partial view.
Update (when I answered, the question asked when to use a User Control...):
A server control is appropriate when you want to bundle assets and functionality for wider distribution than a single project. It is more complex to develop a server control than it is a User Control, but a server-control allows you to completely encapsulate HTML, CSS, JavaScript, images, and server-side logic within a single DLL.
Conversely, a User Control is much easier to develop, but cannot contain assets such as external CSS/JS or images. User Controls are basically just partial bits of an ASPX page.
Unless you know that you need the features of a server control, I would always recommend a User Control for simple de-duplication of content that's repeated in multiple ASPX pages.
A User Control enables you to create your own custom control modules. They're useful because they are reusable, meaning you don't have to duplicate a lot of code. You can embed them in ASP.net pages, and you can define methods and properties for them.

ASP.NET 2.0 -how do I include files containing server-side code?

I want to be able to load a customized log in page depending on a couple of parameters passed into the querystring.
Each customized login page needs to be able to dynamically display log in errors and possibly have other variables passed in.
Let's say the dynamic login page looks like this (over-simplification here):
<form>
<% if (has_errors) { Response.Write(error_msg); } %>
<input type="text" name="email">
</form>
If the aspx page loads the file like this:
Response.writefile("path/to/custom/page");
the code shows up in the output and doesn't get processed. I have tried other ways to load the file contents (something similar to classic ASP includes) but get the same results every time.
I could have all the custom pages set up as user controls, but I need 100% control over the css, js, and html - and the documentation I read here indicates that I won't have that level of granularity.
link text
PLUS - I'm stuck in a .net 2.0 environment - so .NET MVC is not available to me
Any help/suggestions?
but I need 100% control over the css,
js, and html
You won't get 100% over the page but you will have control inside the User Control instance. Also, many times, you can override these technologies like CSS, from within your control.
In the end because all controls are solified into one big HTML page you will have the same level of control as you would in any single web page with client-side technologies.
You can build a Web UserControl to represent log/in and then include an instance of that control onto any page, in any place, across multiple pages if you wish.
(See the Topics on that MSDN help page about how to create and use it).
Other useful references (these are various angles on the same subject).
Creating a Web user Control in .NET
ASP 101 - User Controls
This should provide a good start to keep looking, if this is the kind of info you think you need.
Internals
The User Control can have its own logic, access the browser querystring, access the page Session, Application, etc. pretty much anything it needs to know for itself to work.
Object Oriented
Additionally, because a User Control is also an object, you can add your own public methods and properties to it through which you can interact to communicate with the control intance on the page (just like you interact with other web controls like Button.Text="click", TextBox.BackColor = System.Drawing.Color.Blue, etc).
Other Options - Dynamic control loading
You might want to consider loading controls dynamically at runtime using the Page.LoadControl(..) method:
Loads a Control object from a file
based on a specified virtual path.
MyControl myControl1 = (MyControl)LoadControl("TempControl_Samples1.cs.ascx");
PlaceHolder1.Controls.Add(myControl1);

Register Startup Script Control

I am looking to make a web control where I can register client startup scripts inline with my aspx because I hate registering in the codebehind!
An example of what I have so far:
<Ben:StartupScript runat="server">
var form = document.getElementById("<% =form1.ClientID %>");
</Ben:StartupScript>
Currently, I am overriding the OnPreRender method of the control, rendering the contents of the control to a string and then manually registering that string as a startup script using ClientScript.RegisterStartupScript on the Page. I also override the Render method in order not to render the control. I should also note that I have the ParseChildren attribute set to false and the PersistChildren attribute set to true.
All seems to be working well, but my control allows other web controls inside it (such as Button). Apart from being unintuitive, this can result in runtime errors. I would love to be able to clear the controls but this is impossible given the <% ... %> code block.
So, is it possible to prevent developers from embedding child controls whilst still allowing code blocks?
Also, is this idea any good or is it fundamentally flawed? Lol.
Thanks a bunch,
Ben
it sounds like a good idea, but if you spend too much time fighting the inherited/default behaviors then it may be more trouble than it's worth
if this is a one-shot issue, a cheap-hack solution is to just directly embed your scripts in the header of a master page ;-)
on the other hand, allowing developers to embed their own scripts as children of your web control might be useful
If you are using master pages, add another control in your section. That way you can easily add css/js to your headers in your child pages.
ClientScript.RegisterScript is mostly for user/server controls,

Resources