Off the top of my head, I don't see any reason why you couldn't structure an ASP.NET custom web control (ASCX file) to output only XML.
If you avoid using controls in the System.Web.UI namespace, and just use XML tags and sub-controls, which also render only XML, you should end up with a perfectly valid XML document being rendered.
Am I right, or is there something I'm missing?
If you want to generate an XML document and return that to the client, then it's probably easier if you create a http handler (IHttpHandler) instead of using a page and user controls.
You are missing that the control has to be within a page which would have some HTML output for a tag marking the start and finish of the control though there may be a way to override that.
Your idea could work out if your ASCX's generate pure XML, and you overwrite the Page's Render methods to replace the HTML tags that form HTML, BODY and FORM etc. elements.
The question is what you would gain with this approach over simply generating an XML document and building a class library which generates those XML fragments you wanted to generate using the ASCX's.
Related
I have html Page with js file on the head.
when the js file run :
call ajax request to get data
the callback run js to create html elements and populate the page.
Is it better (performance) to have page with server side to take care for creating the html elements and populate the page?
But to answer your question... yes, it is better (performance-wise) to have the back-end generate the HTML.
It's bad practice though. Here are some reasons why:
Advantages of createElement over innerHTML?
I would like for a webmethod to return a string of pure html.
The html isnt anything too fancy, a table and a couple form fields populated with values from a database.
Is their an easy way to build html within html? currently I am just dynamically building up a string, but it just feels dirty.
I could make a full blown aspx page, and then just strip out the bits I dont want from the resulting page leaving the plain html behind. but that also feels dirty.
Or there is the templating option (nvelocity etc) but thats seems like overkill.
any suggestion on something more efficient.
Tx
You can build a template file like xml to write the basic of your html with {0}{1}{2}{n} to put static content in it
Manipulate this template server side as you wish. You can add a list of data into this template.
Create a literal control on your page.
Put the server side created html in to you literal control. (myLiteral.Text)
You can create a basic asp.net file and add the html template in it by adding it from the literal control.
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.
Is there a way to write pure HTML when i'm developing my ServerControl in ASP.NET?
I want to create my control as .dll file. But when I'm writing my control I can only add HTML tags and attributes in C# in my .cs file.
And so i am forced to use this in my RenderContents() method:
output.RenderBeginTag(...
output.AddAttribute(...
output.RenderEndTag(...
instead of for example:
<div attribute1="value"></div>
is there a workaround of this problem?
Unfortunately only user controls (ASCX) allow for this type of approach (delcarative markup) but they cannot be packaged into DLLs. I've always hated this restriction, to me it's a code smell programmatically generating markup, but this is what we must live with!
If you have very static markup you could always put it into a resource file (resx) instead of outputting the HTML programmatically
I wish to use xml and xsl to generate controls on an asp.net page.
I currently have a asp.net content page that contains a xml control. When the page is loaded, an xml file is loaded and the required element is extracted and set as the xml control's DocumentContent and the xml control's TransformSource is set to the appropriate xsl file.
In the xsl file, I wish to use templates to create asp.net controls depending upon the contents of the xml. Is there an easy way of doing this with the xml control on the content page?
Register a namespace in your XSL so that you can put .NET server-side tags into it. Run your XSL transform against your XML. Run the result of your transform through Page.ParseControls(). This will give you a nice control hierarchy. Add the output of that function to your Controls collection (or the controls collection of your placeholder) and you're good to go.
There are LOTS of caveats to using dynamic controls in .NET, so beware.
The generated output of transform is not parsed to be added to the page as set of controls. Rather the generated output is sent to the response. Therefore you cannot apply a transform to an XML control that will generate new controls.
There may be a way to create the transform result and invoke some parsing that can be applied to the page but that would not meet your 'easy' requirement.
I don't know of any easy way to do it, but there are a few systems out there which generate the aspnet markup on the fly then send it to the aspnet runtime from a memory stream (or similar).
I think umbraco uses a system something like that, but the initial builder mechanism is probably a little more low level than an aspnet control. It might be achievable using an httpmodule or something else that gets hit earlier in the request pipeline.