I'm new to jquery and asp.net so please forgive if this is an obvious question. I'm using a jquery autocomplete plugin which requires that the page it looks up asynchronously for data is in this format as pure text only:
product1|price1
product2|price2
product3|price3
WITHOUT ANY OTHER HTML MARKUP. Any other html tags seems to cause problems.
Normally for a page like that I would use a repeater and some standard database calls and output the 2 fields. This however creates html tags.
How can I output this data as text only with no other markup whatsoever?
If you have a bare page with no master page referenced a repeater shouldn't produce any html. Make sure in the HTML view you only have:
<asp:Repeater ID="outRepeater" runat="server">
- your template here
</asp:Repeater>
An alternative would be to add a new Handler to your project which is a class that implements the IHttpHandler interface. This would allow you to output your code directly. This would end up looking like:
public class MyOutputHandler : IHttpHandler {
public bool IsReusable { return false; }
public void ProcessRequest(HttpContext context) {
context.Response.Write("product1|price1");
}
}
If you have added this to a project as a new Handler (from add items) it should have a .ashx extension. Otherwise you'll need to register it in your web.config with its type and filename.
Related
The ASP.NET function ClientScript.RegisterClientScriptBlock can be used to register a chunk of JavaScript code that will be added to the page when it's rendered. The idea here is that you could have multiple instances of various user controls trying to register the same script over and over, but this ensures that it will only be included once.
The problem is, you don't really have any control over where the code is added to the page. This will insert the code inside the BODY tag of your page, but I need to add something (not limited to JavaScript code) into the HEAD block.
I'm well aware of various methods of adding something to the HEAD block via a ContentPlaceHolder block or by "Head.Controls.Add but these options do not address the problem of the same thing being added multiple times.
Is there an existing way to do this, or do I have to write a class that does something similar to ClientScript.RegisterClientScriptBlock except targeting the HEAD block?
I threw together a user control. There's nothing in the markup at all, so you can just add a new Web Forms User Control to your project and put this in the code behind:
public partial class ScriptControl : System.Web.UI.UserControl
{
private Dictionary<string, string> _scripts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public void RegisterScript(string key, string script)
{
if(!_scripts.ContainsKey(key)) _scripts.Add(key, script);
}
protected override void Render(HtmlTextWriter writer)
{
writer.WriteFullBeginTag("script");
foreach(var script in _scripts.Values) writer.Write(script);
writer.WriteEndTag("script");
}
}
Just add the directive to your page markup:
<%# Register TagPrefix="uc" TagName="ScriptControl"
Src="ScriptControl.ascx" %>
(where "ScriptControl.ascx" is whatever you've named the control)
and then you can add it wherever you need to, including in the header.
<head runat="server">
<uc:ScriptControl id="HeaderScriptControl" runat="server"/>
</head>
The usage is pretty much the same:
HeaderScriptControl.RegisterScript("myScript",
#"alert(""hello, world!"")");
What's the "skeleton" code for using CsQuery in the code-behind of a MasterPage in order to modify the HTML output? I need to be able to modify everything in the <body> of the HTML?
I'm hoping to use CsQuery to "touch-up" the HTML output of a Dynamic Data website without rewriting / messing with the default code.
Just looking for sample code specific to MasterPage code-behind? Thanks.
There is an example in the CsQuery project that shows how to do this (which I just made sure was working right!) in the CsQuery.WebFormsApp project.
The core of the usage looks like this. You must override the Render method in a class that inherits Page, and use this instead of Page as the base class for the codebehind in an aspx page:
public class CsQueryPage: System.Web.UI.Page
{
public CQ Doc { get; protected set; }
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
// most of the work is done for you with the
// `CsQuery.WebForms.CreateFromRender` method
var csqContext = WebForms.CreateFromRender(this, base.Render, writer);
// if you are using update panels, this lets you also manipulate that
// HTML, otherwise you don't need the IsAsync part
if (csqContext.IsAsync)
{
foreach (var item in csqContext.AsyncPostbackData) {
Cq_RenderUpdatePanel(item.Dom,item.ID);
}
}
else
{
Doc = csqContext.Dom;
Cq_Render();
}
// writes the altered content to the base HtmlTextWriter
csqContext.Render();
}
protected virtual void Cq_Render()
{ }
protected virtual void Cq_RenderUpdatePanel(CQ doc, string updatePanelId)
{ }
}
The two virtual methods are where you can alter the dom, which is populated in the Doc property of the CsQueryPage object - the intent of leaving them unimplemented here is that each aspx page that inherits CsQueryPage can optionally override them and make changes to the DOM.
To see how this works in practice just pull down the CsQuery code from github and run the example.
The same technique can be used for a UserControl which is also shown in the example. I don't actually show how to do it with MasterPage but it's very much the same-- MasterPage derives from UserControl, you just override it's Render method same as the other situations.
On my current project I need to add a functionality that allows the user to view a thumbnail of their uploaded PDF. I've found a handy component that achieves this (the basic version is free, but it's enough for my current needs). Anyways, the control is pretty outdated (2010), therefore there doesn't seem to be MVC support. On the demos they depict usage of the control as such:
The View's Markup:
<form method="post" runat="server" enctype="multipart/form-data">
<asp:Panel ID="thumbnailsPanel" runat="server" />
</form>
The thumbnail control is instantiated via code, the byte array which represents the thumbnail is passed to the control and the control is added to thumbnailsPanel
<script runat="server">
protected void DisplayThumbs_Click( object sender, System.EventArgs e )
{
Thumbnail thumbnail = new Thumbnail();
thumbnail.SessionKey = sessionID;
thumbnail.Index = i;
thumbnailsPanel.Controls.Add( thumbnail );
}
</script>
Given that I can't declare a Thumbnail control in my razor view, how would I used this control in MVC? I've spent a few hours trying to make this control MVC friendly to no avail, the best I've come up with is to include a .ASPX view (not.cshtml) in my project and render the Thumbnail control on that view. Obviously this is not desirable.
So how would you go about using a ASPX server controls in MVC? Is the idea a bad one altogether and should not be practised?
I worked around it in a project of mine by reimplementing the control as a HtmlHelper. Assuming the control isn't too complicated then it should work for you too. Do this:
Dump the Control's source using Reflector
Massage the source so it actually compiles (as source from Reflector doesn't usually compile straight away)
Identify what state the control has. Convert the state from member properties into members of its own new ViewModel class.
Find the Render method and convert it to a HtmlHelper that uses ViewContext.Writer
For example:
public class FooControl : Control {
public String Message { get; set; }
public override void Render(HtmlTextWriter wtr) {
wtr.WriteLine("<p>");
wtr.WriteLine( message );
wtr.WriteLine("</p>");
}
}
Becomes this:
public class FooViewModel {
public String Message { get; set; }
}
// This method should exist in a static Extensions class for HtmlHelper
public static void Foo(this HtmlHelper html, FooViewModel model) {
HtmlTextWriter wtr = html.ViewContext.Writer;
wtr.WriteLine("<p>");
wtr.WriteLine( model.Message );
wtr.WriteLine("</p>");
}
I am trying to use the ASP.NET (3.5) "Routing Module" functionality to create custom pages based on the contents of the URL.
Various articles explain how to use ASP.NET Routing to branch to existing pages on the web server.
What I would like to do is create the page on-the-fly using code.
My first attempt looks like this:
public class SimpleRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string pageName = requestContext.RouteData.GetRequiredString("PageName");
Page myPage = new Page();
myPage.Response.Write("hello " + pageName);
return myPage;
}
}
But this throws an HTTPException saying "Response is not available in this context." at the Response.Write statement.
How to proceed?
UPDATE: In the end, I went with an approach based on IHttpModule, which turned out to be rather easy.
You can't write to the response from an IRouteHandler - it's way too early during the request life cycle. You should only write to the response from within the IHttpHandler, which is what the Page is.
As is shown in other examples, you'll have to get a page instance from somewhere that has all the necessary content.
Here's how you can load an existing page:
Page p = (Page)BuildManager.CreateInstanceFromVirtualPath("~/MyPage.aspx");
Or you can create one from scratch:
Page p = new Page();
p.Controls.Add(new LiteralControl(
#"<html>
<body>
<div>
This is HTML!
</div>
</body>
</html>"));
Instead of trying to write directly to the response, you might want to simply add controls to the page. Since the page is brand-new and has no markup, you may have to add all of the HTML elements to make it legal HTML in order to get it rendered correctly. Having never tried this, I have no idea if it will work.
Page myPage = new Page();
page.Controls.Add( new LiteralControl( "hello " + pageName ) );
return myPage;
It's not clear to me that this will have the required HTML, HEAD, and BODY tags. It might be better to create a base page that has skeleton markup that you can just add your controls to and use the BuildManager as in the example to instantiate this page, then add your controls.
Put requestContext before Response.Write, so requestContext.Response.Write
I have developed a server control inherited from WebControl that wraps any number of child controls and changes their output. The control class is very simple and only contains the RenderContents method.
Here is an example of how it has been placed on the page. (Not included: registration of control namespaces.) The intention here is that the rendered output from the RichImageField control will be changed:
<RX:HideWhitespaceControl runat="server">
<PublishingWebControls:RichImageField
FieldName="PublishingPageImage"
runat="server"
id="PageImage">
</PublishingWebControls:RichImageField>
</RX:HideWhitespaceControl>
However when I try to browse to the page none of the code in my control class appears to execute and I receive the following error:
Parser Error Message: Type
'RX.SharePoint.Common.Controls.HideWhitespaceControl'
does not have a public property named
'RichImageField'.
I'm confused about why this error is appearing. There is indeed no public property named RichImageField as this is not a property but rather a child control!
My custom control is being used in a SharePoint publishing site on a page layout so I'm not sure if this error is coming from SharePoint. But it looks like a basic ASP.NET error so what am I missing?
Maybe you need to add the, ParseChildren(false), PersistChildren(true) attributes to your custom control, like:
[ParseChildren(false)]
[PersistChildren(true)]
public class YourControl : WebControl
You need to override the AddParsedSubObject(object obj) method to handle child elements:
protected override void AddParsedSubObject(object obj)
{
if (obj is LiteralControl)
{
// This is pure HTML or text...
}
else if (...)
{
// Handle ASP.NET controls...
}
}