ASP.NET, XSLT and dynamic controls - asp.net

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.

Related

Custom control names (not ID) in ASP.NET to use with JQ.serialize

I am developing a website using mainly AJAX for saving and retrieving data in order to avoid postbacks (or at least full postbacks).
I "prepare" the page in codebehind, and on client I use JQ and Javascript.
When I want to save data I serialize the elements in a container (using JQ) and then AJAX post to send data to the WebMethod.
This is working well but I have to deal with long name elements ("ctl00$MainContent$grdEmployees$ctl03$ddlRole").
Sometimes is difficult to retrive data from the NameValueColletion as the same WebMethod can be called from different pages, so the "name" of the element is not the same as the control may be nested in other container.
Is there a way to set custom names for ASP.NET controls to avoid this issue?
Or other way to achieve this behavior?
Best regards.
Have you tried to use ClientIDMode="Static" which is found in .NET 4.5.
When a page is render the ids all change as you have noted. However, you set the ClientIDMode to static it will render with the ID that you have put for the control itself. That way you can work with the ID of the control instead of the generated id. If you would like to know more here is a like to the MSDNA about ClientIDMode
http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientidmode(v=vs.110).aspx

Making Ajax for Fileuploads in ASP.NET, while keeping track of files in Memory

I need to make a Asp.net control to upload multiple files that sends the files through Ajax.
This control could be used to store the files on a Folder or in the Database, the persistense is going to be decided by the Classes that will use my control, not the Control itself. So i need to achieve a level of flexibility here.
The uploaded files will be stored my Control Class like a List of Files, until the class using my control execute the "official post" which will consume and then finally release the class.
In a simple example a Form using my control would consume the List generated by all the uploads made through my control and upong Save, the form would read my list and persist it the way is best.
The problem here is the approach:
I can't use a updatePanel because it doesn't allow for fileinputs and (afaik) won't keep the state of purelly javascript generated input=files.
It's not possible to use the WebMethod property to send the data since it requires my Method to be static which makes it impossible to feed a in memory object using this method.
The other option would be to use handmade Ajax, which is not that difficult, but I'm not sure how Asp.net will behave, does it keep states between Ajax Calls? Can I access the same in memory object from different calls? will i have to keep track of viewstates or use sessions? is it viable to use sessions or the viewstate(!) to keep uploaded files?
Reforcing: The problem is NOT Uploading the files with ajax, I'm using blueimp.github.com/jQuery-File-Upload , the problem is keeping track of them in the serverside without persisting.
Example
Let me try to explain a little better:
0) I have a control, this control has a property that is a List of the files - List<files> FilesUploaded;
1) On each ajax upload , I add the coming File into the list FilesUploaded.Add(FileComingFromAjax)
2) My controls goes into a form (any form), and when I save the Form BtSave.Click(), the Form class will need to get the list of files and persist so: they access it like this AnyonesForm.MyControl.FilesUploaded. Notice that the files are in Memory and not in the disk or the database.
My doubt is, Will the files be kept after each request? namelly:
Will the method call through ajax, use the Same List?
When i submit the main form, Will the List be accessible by the form class with the files I just uploaded?
Well Actually , I was thinking asp.net would be able to keep the objects between ajax requests, but this is not the case.
I'm going to use sessions, I'm not afraid to add objects to sessions anymore , ASP.net, adding objects to a session variable
Combine jQuery and AJAX like so:
jQuery Ajax File Upload
How can I upload files asynchronously?
to achieve your result.

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.

Html in ASP.NET server control

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

Can you use an ASP.NET web control (ASCX) to render XML?

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.

Resources