Creating a System.Web.UI.Page programmatically in IHTTPHandler - asp.net

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

Related

Inject Html Into a View Programmatically

I have a tricky problem and I'm not sure where in the view rendering process to attempt this. I am building a simple blog/CMS in MVC and I would like to inject a some html (preferably a partial view) into the page if the user is logged in as an admin (and therefore has edit privileges).
I obviously could add render partials to master pages etc. But in my system master pages/views are the "templates" of the CMS and therefore should not contain CMS specific <% %> markup. I would like to hook in to some part of the rendering process and inject the html myself.
Does anyone have any idea how to do this in MVC? Where would be the best point, ViewPage, ViewEngine?
Thanks,
Ian
You could use Html.RenderPartial to insert an HTML fragment somewhere in the page. If you want to insert it in a place not available to the view but only on the master you could place a <asp:ContentPlaceHolder ID="Admin" runat="server" /> placeholder inside the master and in the view simply override it and insert the partial. If placing such a placeholder is not acceptable you could use AJAX like: $('#adminHolder').load('/home/admin');, but I would probably go with the previous approach as it will work in case the user has javascript disabled.
OK this took a bit of messing and the result is a little hacky. But it works and that's all that matters right....
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (!User.Identity.IsAuthenticated || !User.IsInRole("Admin"))
{
// If not admin continue as normal
base.Render(writer);
return;
}
// Taking a leaf out of the move viewstate to the bottom of page playbook
var stringWriter = new System.IO.StringWriter();
var htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
var html = stringWriter.ToString();
var endOfBody = html.IndexOf("</body>") - 1;
if (endOfBody >= 0)
{
var adminConsole = Html.RenderPartialAsString("AdminPanel");
html = html.Insert(endOfBody, adminConsole);
}
writer.Write(html);
}
I implement my own ViewPage overriding the Render method. This checks if the user is logged in as an admin and if they are, it renders a partial at the bottom of the page. Very similar to old skool viewstate hacks in webforms.
Enjoy.

Is there a way to access an object defined on a view in a Master Page in ASP.Net MVC

So I've got a partial in my MVC project that creates a JSON array. I want to move this chuck of code from the top of the html page body to the bottom with the rest of the JS for speed reasons. That is to say I want to store the JSON created as a string in C# and access it on the Site.Master.
What's the best option here?
Thanks,
Denis
When I need to access information in my MasterPage I create a BaseController and set the information in my ViewData :
public abstract class BaseController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
ViewData["JSonObject"] = "json string";
}
}
Just have to inherit all controller from BaseController and it will work.
All views including MasterPage can access ViewData["JSonObject"] now!
Just call RenderPartial in the MasterPage
Use ViewData to pass information around between the views.
In your partial:
ViewData["JsonString"] = ".....";
In the master page:
<%= ViewData[ "JsonString" ] %>
Seems that ViewData is Top down only. So if you assign a value in the partials parent or a controller that'll work but not the other way round. I managed to get it working using Context.Item
Context.Items["JSONFeatures"] = "test"; on Partial
Context.Items["JSONFeatures"].ToString(); on MasterPage
Hope this helps someone. I'm not sure if this is best practices but it works it I know better!

Get MasterPage Hiddenfield Value From a User Class

Is there a way to get a value I am storing in a Master Page hidden field from a User Class which I created and placed in the App_Code folder of my ASP.Net 2.0 Application?
Some examples would preferably in VB.Net is highly appreciated.
Thanks.
To give further details, assume the following:
MasterPage.Master
MasterPage.Master.vb
MyPage.aspx
Mypage.aspx.vb
IN the app_code folder, add a new class, say TESTClass.
I have placed some logic in master page. MyPage.aspx uses the Masterpage.master as its master page. In the master page, the logic which I did stores a value into a hidden field.
in my TestClass, how do I access the master page hidden field?
Please take note that TestClass is NOT a user control but a user defined class, which contains some Business-Specific logic which is accessed by myPage.aspx.vb.
I tried ScarletGarden's suggestion but it did not seem to get the Masterpage Hiddenfield which I need to get the value.
Would something like this work?
((HiddenField)this.Page.Master.FindControl("[hidden control id]")).Text
You can get it by these :
hiddenControlValue = HttpContext.Current.Request["hiddenControlId"]
or you can pass your page to your method that belongs to your class under App_Config, and reach it as :
public static string GetHiddenValue(Page currentPage)
{
return currentPage.Request["hiddenValue"];
}
or you can get it over context :
public static string GetHiddenValue()
{
return HttpContext.Current.Request["hiddenValue"];
}
hope this helps.
EDIT: I re-read the question after answering, and realize my answer was probably not quite what you were after. :/
Jared's code might work, but you can also try the following.
In your MasterPage, make the HiddenField a public property, and store the content in the ViewState to make keep it during post backs.
Something like so:
public HiddenField theHiddenField
{
get
{
if (ViewState["HiddenField"] == null)
return null; //or something that makes you handle an unset ViewState
else
return ViewState["HiddenField"].ToString();
}
set
{
ViewState["HiddenField"] = value;
}
}
You then have to add the following to your ASCX-file:
<%# Reference Control="~/Masterpages/Communication.Master" %>
You then access it thusly.
Page mypage = (Page) this.Page; // Or instead of Page, use the page you're actually working with, like MyWebsite.Pages.PageWithUserControl
MasterPage mp = (MasterPage) mypage.Master;
HiddenField hf = mp.theHiddenField;
Sorry if the answer got a bit messy. This is, of course, how to do it in C#, if you want to use VB have a look at this link for the same idea.

asp.net output data from DB without any html markup

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.

How do I get a custom IHttpHandler to Be Capable of Handling Postbacks?

I am writing a custom HTTP handler to provide an edit form for a grid using existing user controls. Basically, my handler creates the page, form, header, and other controls necessary to be able to render the existing user controls properly and at the end of ProcessRequest, I use Server.Execute to execute the page that was dynamically created. I am doing this because the solution where this resides is a user controls project and there are no pages, nor can we add any. This needs to be reusable for several projects.
This works great up until the point where the user controls added to this "page" require the usage of the postback mechanism. In the user control Page.IsPostBack is always false and control events (like a button click) are not handled. It is obvious that I am missing some critical piece from how a typical ASP.NET page works. The Page class is just an implementation of an IHttpHandler, but there is a lot of code that I don't think should be necessary to get the basic functionality to work here.
Any ideas?
Here's the basic code from my base HTTP handler. I have other classes that inherit from this base handler to add the actual user controls to the form of the page.
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "text/html";
HtmlGenericControl htmlPage = GetHtml();
AddTitle();
htmlPage.Controls.Add(_head);
HtmlGenericControl htmlBody = GetBody();
_form.Action = context.Request.Url.ToString();
_form.Method = "POST";
htmlBody.Controls.Add(_form);
htmlPage.Controls.Add(htmlBody);
AddAjaxManager();
AddScriptManager();
_page.Controls.Add(htmlPage);
//_page.ProcessRequest(context);
context.Response.CacheControl = "No-Cache";
context.Server.Execute(_page, context.Response.Output, true);
}
public bool IsReusable { get { return false; } }
To make this work, I inherited from Page instead of implementing IHttpHandler. You do still need to build out the entire HTML of the page, but you get all the wonderfulness (or not) of the ASP.NET WebForms page lifecycle when you do this.

Resources