How to display the message Box within the Content Page..?
After updating profile..I want to display a Message Box in content page..
Please give your suggestions.. Thanks in advance.
You could use the Page.RegisterStartupScript method.
if (UpdateProfile())
Page.RegisterStartupScript("startup", "<script>alert('your profile has been updated..');</script>");
Assuming of course that UpdateProfile() does the work and returns a boolean indicating success :)
Alternatively (because that method is obsolete), you could use the ClientScriptManager.RegisterStartupScript method instead.
if (UpdateProfile())
Page.ClientScript.RegisterStartupScript(this.GetType(), "startup", "<script>alert('your profile has been updated..');</script>", false);
write this method first
public void MsgBox(String ex, Page pg,Object obj)
{
string s = "<SCRIPT language='javascript'>alert('" + ex.Replace("\r\n", "\\n").Replace("'", "") + "'); </SCRIPT>";
Type cstype = obj.GetType();
ClientScriptManager cs = pg.ClientScript;
cs.RegisterClientScriptBlock(cstype, s, s.ToString());
}
after whenever you need message box just follow this line
MsgBox("Your Message!!!", this.Page, this);
The error you are seeing is caused by your content page somehow trying to inject the javascript to create the alert box outside of the Content control.
One way of doing this that should work is to inject the javascript at the master page level.
To do this expose a method in you master page code behing like the following:
public void ShowAlertMessage(String message)
{
string alertScript = String.Format("<Script Language='javascript'> alert('{0}');</script>", message);
Page.ClientScript.RegisterStartupScript(this.GetType(), "Key", alertScript, false);
}
Then, from the content page you can call this method on the Master object:
protected void UpdateProfile_Click(object sender, EventArgs e)
{
YourMasterPage master = (YourMasterPage) Master;
master.ShowMessage("Profile updated.");
}
This method also has the nice benefit of encapsulating your MessageBox logic for all your content pages.
One caveat on the above is that I can't for the life of me reproduce the error you are seeing, I've tried every combination of master/content markup I can think of and can't get the error. Any of the other examples provided here in the other answers work happily for me.
Response.Write("[script] alert('message here');[/script]");
stackoverflow won't allow the real tags replace the [ with < and the ] with >
Related
I am using a asyncfileUpload control in my page, and that page is derived from a master page.
My motive to use this control is only to upload an image and show that image on the same page.
But when i am trying to upload an image, i am getting an Exception i.e.: "Unhandled Exception: $get("imgUpload") is null".
I am using the following function on ClientUploadComplete:
<script type="text/javascript">
function uploadComplete(sender, args) {
var FileName = args.get_fileName();
$get("imgUpload").src = "../ajax/upload/" + FileName;
}
</script>
and i have also set the ClientIDMode=AutoID.
And i am using the following code under the UploadedComplete event:
protected void AsyncFileUpload1_UploadedComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
string strPath = MapPath("~/ajax/upload/") + Path.GetFileName(e.FileName);
AsyncFileUpload1.SaveAs(strPath);
imgUpload.ImageUrl = strPath;
}
In a normal page, when I try the above It is working correctly but in case of Derived page (from Master Page) it is arising the exception.
Please help me out here to fix this problem.
With Regards,
Ravindra Kumar
AutoID will rename the control based on rendering order, so when the master page is added in, it changes everything. Have you taken a look at your rendered source to verify the rendered control id? Try changing ClientIDMode to "Static"
I have an app full of pages and user controls, many of which have one or more label controls on them for displaying various different messages to the user.
Example: the AddCompany.ascx user control, normally used on the Company.aspx page (with App.Master MasterPage) has a label on it called "OutOfCreditLabel" with Text="Error: You cannot create a new company, as you are out of credit". The code checks the credit and shows the label if needed.
I want to get rid of all these labels all over the place and just have a method I can call from anywhere like
ShowUserMessage("Text goes here");
In previous projects I've implemented this as a single label on the master page and public method in the .master.cs - as long as the page has the line
<%# MasterType VirtualPath="~/App.master" %>
in it, this works - but I can't get it to work on user controls (.ascx.cs). Is there a trick to this?
Or... Is there a better way?
What would you recommend for a "global" user message method that works from anywhere in the site?
Any nice jQuery solutions, perhaps?
Update
RPM1984 has asked for further clarification, so I'm trying to ask this a different way:
I need a method I can call from the code-behind (of a page or a user control) which will then display whatever text I specify to the user, like how stackoverflow tells you about new answers to your question when you next visit the site. It can be up the top of the window (like SO) or somewhere on the page, doesn't matter. What matters is that it's a "global" approach, rather than having various javascript alerts and asp:label's littered over every other page and user control in the project.
Something like this scenario:
A user clicks the "Create Widget" button on my "widget manager" user control on my page. In the event handler is:
if (User.IsOutOfCredit)
{
ShowUserMessage("Sorry, you cannot create widgets; you are out of credit.");
}
This results in the user seeing "Sorry, you cannot create widgets; you are out of credit." Either in a pop-up or red text in the page somewhere or at the top like StackOverflow, anything is fine
Does that make sense?
Why not a simple HTML "old-school" extension method? (i.e static method)
namespace Web.Helpers
{
public class HtmlHelpers
{
public static string Label(string target)
{
var dynamicText = SomeWhere.GetSomeCoolText();
return String.Format("<label for='{0}'>{1}</label>", target, dynamicText);
}
}
}
Then in your HTML:
<%= HtmlHelpers.Label("sometarget") =>
In your main master page, just import the namespace:
<%# Import Namespace="Web.Helpers" %>
EDIT after question updated
Ok, i see what you're trying to do now. I would recommend doing it all client-side.
That is, in your main master page, create an initially hidden <div> with a unique id:
<div id="message" style="display: none"></div>
Then create a helper method somewhere in your web project, rendering out some script.
public void DisplayMessage()
{
string message = SomeWhere.GetSomeCoolText();
StringBuilder script = new StringBuilder();
script.AppendFormat("$('message').show().append("<span>{0}</span>")", message);
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), script.ToString(), true);
}
Of course, this is just a guideline. You dont have to use jQuery, you don't have to hardcode the script in the method. You could create a JavaScript function that accepts a string and modifies the HTML of the div, then just call the function.
It all depends on how complicated your "message" is, if you need special server controls, internationalization, etc.
But this is certainly the easiest way to accomplish what you want (IMHO).
Personally, I'd prefer using the HttpContext.Current.Items dictionary with a custom control. Similar to Keith Bluestone's approach, but doesn't require an arbitrarily named control on the page; it makes it very clear what's going on. You could package it into one class as a server control easily enough, but here it is to drop into a standard web project.
To register a message in your code behind:
SiteMessageUtility.Add("Test message");
To display in your page, or master page, or wherever, really:
<%# Register TagPrefix="custom" TagName="SiteMessage" Src="~/Controls/SiteMessage.ascx" %>
<custom:SiteMessage runat="server" />
Here's the files you'll need:
~\App_Code\SiteMessageUtility.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public static class SiteMessageUtility
{
public static void Add(string message)
{
string currMessage = HttpContext.Current.Items["message"] as string;
if (currMessage == null)
{
HttpContext.Current.Items["message"] = message;
}
else
{
HttpContext.Current.Items["message"] = currMessage + "<br/>" + message;
}
}
}
~\Controls\SiteMessage.aspx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SiteMessage.ascx.cs" Inherits="Controls_SiteMessage" %>
<asp:Literal runat="server" ID="message" />
~\Controls\SiteMessage.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Controls_SiteMessage : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void OnPreRender(EventArgs e)
{
message.Text = (string)HttpContext.Current.Items["message"];
base.OnPreRender(e);
}
}
On the master page add the following controls:
the hfMsg hidden field will hold the message that will be displayed
and the hfCtrl will hold the name of the html control that will display this message which will be in this example lblMsg.
<label id="lblMsg" style="background-color:Yellow; border:solid 1px; width:200px;height:100px;display:none;"></label>
<asp:HiddenField ID="hfMsg" runat="server" />
<asp:HiddenField ID="hfCtrl" runat="server" />
NOTE:you can add another html control with a different id on an ASCX control and use it to display the message instead of the lblMsg.
and the following script:
<script language="javascript" type="text/javascript">
var msg = $('#<%= hfMsg.ClientID %>').attr("value");
var ctrl = $('#<%= hfCtrl.ClientID %>').attr("value");
if (msg != undefined && msg != "") {
$("#" + ctrl).html(msg);
$("#" + ctrl).show();
}
else {
$("#" + ctrl).hide();
}
</script>
NOTE:the script simply checks to see if the hfMsg control has a message to display or not.
and add the following two methods to the master page:
public void ShowMessage(string control, string message)
{
this.hfCtrl.Value = control;
this.hfMsg.Value = message;
}
public void ClearMessage()
{
this.hfMsg.Value = string.Empty;
}
finally you can call the ShowMessage method from any page like this to display a message on the master page:
Master.ShowMessage("lblMsg","hello world!");
and if you have a user control that holds an html label (e.g lblUserMsg) to display the message you can simply call ShowMessage and pass it the name of the label:
Master.ShowMessage("lblUserMsg","hello world!");
Having a SetStatus method in the MasterPage is always the way I've done this, to access the MasterPage from inside a user control, just create a private property in the usercontrol (or create a baseControl class that all user controls inherit from):
private TheNameSpaceOfMyMasterPage.MyMasterPage Master
{
get { return (TheNameSpaceOfMyMasterPage.MyMasterPage)Page.Master; }
}
protected void btnSave_OnClick(object sender, EventArgs e)
{
// Do your stuff...
// Set the Status
this.Master.ShowStatus("blah blah blah");
}
Also if you're using a control to hold the status message remember to disable ViewState on it, otherwise you'll end up with the same status message across postbacks which you don't want.
Some good answers, but...
To Robert W: the master page impl works, but it does require strong coupling (knowledge of) with the master page type. Master pages should generally affect style only, right? E.g. I should be able to change master pages without breaking my app.
SubPortal: yes, very clever, but... too clever for me. Also has master page issue.
RPM1984: again, too clever for me!
MGOwen didn't mention any special DHTML requirements (e.g. update from client side). So why not just implement a simple server-side helper method as he mentioned, find the target control which displays the message, and display it?
The following ShowMessage will find the target message control wherever it is on the page, as well as enable any page to override the default application's ShowMessage behavior if desired.
public static class ASPHelper {
// Defines something that shows a message
public interface IShowMessage
{
void ShowMessage(string msg);
}
// default implementation: finds a target message display control
// wherever it is on the page.
static void ShowMessage_Default(string msg)
{
const string SHOWMESSAGE_CONTROL_ID = "ctlShowMessage"; // or whatever
// find the control
Page currentPage = HttpContext.Current.CurrentHandler as Page;
Control ctlMessage = currentPage.FindControlRecursive(SHOWMESSAGE_CONTROL_ID);
if (ctlMessage == null)
throw new Exception("ShowMessage control not found!" );
Literal ctlMessageLiteral = ctlMessage as Literal;
if (ctlMessageLiteral == null)
throw new Exception("ShowMessage control must be a Literal!");
// Message control should not implement viewstate -- unneccesary
Debug.Assert(ctlMessageLiteral.EnableViewState == false);
// show it
ctlMessageLiteral.Text = msg;
ctlMessageLiteral.Visible = true;
}
// public version for use across app & in pages
static public void ShowMessage(string msg)
{
// Allow the current page to implement its own way of showing
// messages -- provides flexibility.
Page currentPage = HttpContext.Current.CurrentHandler as Page;
IShowMessage showMessageImpl = currentPage as IShowMessage;
if (showMessageImpl != null)
{
// Show using custom message displayer
showMessageImpl.ShowMessage(msg);
}
else
{
// static/global/default version
ShowMessage_Default(msg);
}
}
} // end ASPHelper
To use, simply place a literal control on the page, as in:
<div><asp:Literal
ID="ctlShowMessage" runat="server"
Visible="false"
EnableViewState="false"
/>
</div>
To use, simply call ShowMessage, as in ASPHelper.ShowMessage("insufficient credit"). Hope this is what you're looking for... Keith
Javascript safe popup. Works with Ajax/jQuery.
Namespace Utilities
''' <summary>
''' Utility class for injecting JavaScript into pages. Used primarily for throwing a JavaScript alert box, with correct focus.
''' </summary>
''' <remarks></remarks>
Public Class WriteJava
Region "Public Subs"
Public Shared Sub Script(ByVal script As String, ByRef p As Page, Optional ByVal scriptName As String = "")
If String.IsNullOrEmpty(scriptName) Then
scriptName = GetScriptName(p)
End If
If Not p.ClientScript.IsStartupScriptRegistered(scriptName) Then
ToolkitScriptManager.RegisterStartupScript(p, p.GetType, scriptName, script, True)
End If
End Sub
Public Overloads Shared Sub Alert(ByVal MyAlert As String, ByRef p As Page)
Script("alert('" & Format(MyAlert) & "');", p)
End Sub
Private Shared Function Format(ByVal value As String) As String
Return value.Replace("'", "\'").Replace(Chr(13), "\r").Replace(Chr(10), "\n")
End Function
Private Shared Function GetScriptName(ByVal p As Page) As String
Dim i As Integer = p.AppRelativeVirtualPath.LastIndexOf("/")
Dim pageName As String = p.AppRelativeVirtualPath.Substring(i + 1)
Return pageName
End Function
End Region
End Class
End Namespace
Use by calling:
Utilities.WriteJava.Alert("DANGER WILL ROBINSON", Me.Page)
I was looking for a site-wide way to display message to the user. I found jnotifica. It's similar to stackoverflow's bar at the top of the page.
The author's site appears to be down at the moment.
Raise an event in the user control, subscribe to the event from the page. The event handler updates your custom page property. Seems like the least amount of moving parts.
I would like to suggest to use a class for custom page(Inherited from System.Web.UI.Page) inside that add follwing as
protected void AlertError(string ErrorString)
{
StringBuilder scriptBuidler =
new StringBuilder(#"<script type='text/javascript' language='javascript'>");
scriptBuidler.Append(#"alert('");
scriptBuidler.Append(ErrorString);
scriptBuidler.Append(#"');");
scriptBuidler.Append(#"</script>");
AjaxControlToolkit.ToolkitScriptManager.RegisterClientScriptBlock
(this, typeof(Page),
"Patient Detail Not Found",
scriptBuidler.ToString(),
false
);
}
and inherit all your pages from this class instead of inherinting from system.web.ui.page
and use this function to to show your messages to your clients
Where is the best part of asp.net page or code behind to register RegisterClientScriptBlock.
You have a bunch of options.
Register script includes in your <head> section or do inline <script> tags. I prefer to have my scripts at the bottom of the page though.
You can also register it at the Page level in your Page_Load (or any other event) by calling ClientScript.RegisterClientScriptBlock and passing it the script you want. Remember that if you do go with RegisterClientScriptBlock, you will need to make sure that you register the code with every page load so that is why I would recommend the Page_Load event if you want to use this method.
For example:
protected void Page_Load(object sender, EventArgs e)
{
AddClientSideJavascript();
// Do other stuff
}
private void AddClientSideJavascript()
{
// Register some client script code
Type someType = this.GetType();
if (!ClientScript.IsClientScriptBlockRegistered(someType, "TESTSCRIPT"))
{
string script = "function ShowAlert() { alert('Test'); }";
ClientScript.RegisterClientScriptBlock(someType, "TESTSCRIPT", script, true);
}
// Register more here... etc...
}
Just make sure you don't include it the portion of your Page_Load that is wrapped with the if (!IsPostBack) check or else your scripts will not get registered after any postbacks.
The correct answer is - at any point within page_load.
We are rendering usercontrols dynamically like this:
public string RenderControl(string pathcontrol)
{
string html;
var page = new Page();
var control = page.LoadControl(path);
page.Controls.Add(control);
// do stuff to the control (give it some data to work on)
using (var writer = new StringWriter())
{
HttpContext.Current.Server.Execute(page, writer, false);
html = writer.ToString();
}
return html;
}
This lets us the same user controls when rendering pages normally as we do when rendering responses to ajax calls. However, when adding controls which themselves contain a scriptmanagerProxy we run into the problem that the newed up Page object doesn't contain either a ScriptManager or the HtmlForm in which the ScriptManager needs to run.
Is there any way around this?
Yours
Andreas
As others have said you can add a ScriptManger dynamically easily enough [ Add ScriptManager to Page Programmatically? if your Page object is complete.
Can you try using BuildManager.CreateInstanceFromVirtualPath() to create the Page object instead? You issue may be how you create that object. There's a bit more to creating a new page than newing up the Page object.
Eg.
Page page
= BuildManager.CreateInstanceFromVirtualPath("~/Test.aspx", typeof(Page))
See also http://www.west-wind.com/weblog/posts/120530.aspx for a little more background.
Can you do something like this:
page.Form.Controls.AddAt(0, New ScriptManager())
Edit: I think you'd also need to add your control to the page's form, not just to the page itself, right? It's my understanding that the form is created with the page, but if not you should be able to just do:
page.Form = new HtmlForm()
You may also need to do something like:
page.Controls.Add(page.Form)
Sure, the trick is to add it in a page's Init event handler. You can use:
Page.Init += delegate {
// check for script manager
if( ScriptManager.GetCurrent(Page) == null ) {
ScriptManager m = new ScriptManager();
m.ScriptMode = ScriptMode.Release;
Page.Form.Controls.AddAt(0, m);
}
}
I'd recommend avoiding dynamically adding forms to your page if you can. For example, the above code snippet assumes a form is already present on the page.
Update
Sure, thanks for pointing that out Andreas. Here's an update. So, there is no setter for Page.Form - but you are correct in that you can add a new HtmlForm to the Controls collection. Once added, the Page.Form property is no longer null. That will allow you to add the ScriptManager dynamically as seen above. Here is a code sample that shows this working (ASPX file is a simple page without a server side form):
public partial class Pages_Test_DynamicFormSample : Page {
protected void Page_Init(object sender, EventArgs e) {
Controls.Add( new HtmlForm() );
ScriptManager m = new ScriptManager();
m.ScriptMode = ScriptMode.Release;
Form.Controls.AddAt(0, m);
}
protected void Page_Load(object sender, EventArgs e) {
// ScriptManager test
var t1 = new System.Web.UI.WebControls.TextBox();
var t2 = new System.Web.UI.WebControls.TextBox();
Form.Controls.Add( t1 );
Form.Controls.Add( t2 );
ScriptManager.GetCurrent(Page).SetFocus( t2 );
}
}
Enjoy - btw, setting the ScriptManager's ScriptMode to Release obviously isn't required. We do it just to avoid some JavaScript bugs found in the Debug version of the ASP.NET script runtime.
I'm dynamically loading user controls adding them to the Controls collection of the web form.
I'd like to hide user controls if they cause a unhandled exception while rendering.
So, I tried hooking to the Error event of each UserControl but it seems that this event never fires for the UserControls as it does for Page class.
Did some googling around and it doesn't seem promising. Any ideas here?
mmilic, following on from your response to my previous idea..
No additional logic required! That's the point, your doing nothing to the classes in question, just wrapping them in some instantiation bubble-wrap! :)
OK, I was going to just bullet point but I wanted to see this work for myself, so I cobbled together some very rough code but the concept is there and it seems to work.
APOLOGIES FOR THE LONG POST
The SafeLoader
This will basically be the "bubble" I mentioned.. It will get the controls HTML, catching any errors that occur during Rendering.
public class SafeLoader
{
public static string LoadControl(Control ctl)
{
// In terms of what we could do here, its down
// to you, I will just return some basic HTML saying
// I screwed up.
try
{
// Get the Controls HTML (which may throw)
// And store it in our own writer away from the
// actual Live page.
StringWriter writer = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
ctl.RenderControl(htmlWriter);
return writer.GetStringBuilder().ToString();
}
catch (Exception)
{
string ctlType = ctl.GetType().Name;
return "<span style=\"color: red; font-weight:bold; font-size: smaller;\">" +
"Rob + Controls = FAIL (" +
ctlType + " rendering failed) Sad face :(</span>";
}
}
}
And Some Controls..
Ok I just mocked together two controls here, one will throw the other will render junk. Point here, I don't give a crap. These will be replaced with your custom controls..
BadControl
public class BadControl : WebControl
{
protected override void Render(HtmlTextWriter writer)
{
throw new ApplicationException("Rob can't program controls");
}
}
GoodControl
public class GoodControl : WebControl
{
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<b>Holy crap this control works</b>");
}
}
The Page
OK, so lets look at the "test" page.. Here I simply instantiate the controls, grab their html and output it, I will follow with thoughts on designer support etc..
Page Code-Behind
protected void Page_Load(object sender, EventArgs e)
{
// Create some controls (BadControl will throw)
string goodHtml = SafeLoader.LoadControl(new BadControl());
Response.Write(goodHtml);
string badHtml = SafeLoader.LoadControl(new GoodControl());
Response.Write(badHtml);
}
Thoughts
OK, I know what you are thinking, "these controls are instantiated programatically, what about designer support? I spent freaking hours getting these controls nice for the designer, now you're messing with my mojo".
OK, so I havent really tested this yet (probably will do in a min!) but the idea here is to override the CreateChildControls method for the page, and take the instance of each control added on the form and run it through the SafeLoader. If the code passes, you can add it to the Controls collection as normal, if not, then you can create erroneous literals or something, up to you my friend.
Finally..
Again, sorry for the long post, but I wanted to get the code here so we can discuss this :)
I hope this helps demonstrate my idea :)
Update
Tested by chucking a control in on the designer and overriding the CreateChildControls method with this, works fine, may need some clean up to make things better looking, but I'll leave that to you ;)
protected override void CreateChildControls()
{
// Pass each control through the Loader to check
// its not lame
foreach (Control ctl in Controls)
{
string s = SafeLoader.LoadControl(ctl);
// If its bad, smack it downnnn!
if (s == string.Empty)
{
ctl.Visible = false; // Prevent Rendering
string ctlType = ctl.GetType().Name;
Response.Write("<b>Problem Occurred Rendering " +
ctlType + " '" + ctl.ID + "'.</b>");
}
}
}
Enjoy!
This is an interesting problem.. I am still pretty fresh when it comes to custom controls etc, but here are my thoughts (feel free to comment/correct people!).. (I am kinda thinking/writing out loud here!)
If an error occurs during rendering, in some cases, would it not be too late? (since some of the controls HTML may have already been sent to the Writer and output).
Therefore, would it not be best to wrap the user control's Render method, but rather than passing it the reference to the "Live" HtmlTextWriter, you pass your own, trap any Exceptions raised in this little safety "bubble", if all goes well, you then pass your resultant HTML to the actual HtmlTextWriter?
This logic could probably be slung to a generic wrapper class which you would use to dynamically load/render the controls at run time..
If any errors do occur, you have all the information you need at your disposal! (i.e control references etc).
Just my thoughts, flame away! :D ;)
Depending on where your errors are occurring you can do something like...
public abstract class SilentErrorControl : UserControl
{
protected override void Render( HtmlTextWriter writer )
{
//call the base's render method, but with a try catch
try { base.Render( writer ); }
catch ( Exception ex ) { /*do nothing*/ }
}
}
Then inherit SilentErrorControl instead of UserControl.
Global.asax and Application_Error?
http://www.15seconds.com/issue/030102.htm
Or the Page_Error Event on an individual Page only:
http://support.microsoft.com/kb/306355
void Page_Load(object sender, System.EventArgs e)
{
throw(new ArgumentNullException());
}
public void Page_Error(object sender,EventArgs e)
{
Exception objErr = Server.GetLastError().GetBaseException();
string err = "<b>Error Caught in Page_Error event</b><hr><br>" +
"<br><b>Error in: </b>" + Request.Url.ToString() +
"<br><b>Error Message: </b>" + objErr.Message.ToString()+
"<br><b>Stack Trace:</b><br>" +
objErr.StackTrace.ToString();
Response.Write(err.ToString());
Server.ClearError();
}
Also, Karl Seguin (Hi Karl!) had a Post on using HttpHandler instead:
http://codebetter.com/blogs/karlseguin/archive/2006/06/12/146356.aspx
(Not sure what the permission to reproduce it, but if you want to write up an answer, you got my Upvote ☺)
How about adding a new sub-class of UserControl that error-handles its render and load methods (so that they hide as you wish) and then inheriting from that for your user controls?
I am not sure I understand your response.. How are you loading your controls and adding them to your controls collection?
That was the whole point of the bit added in the "Update" section.. You have the flexibility to use the SafeLoader wherever you please.
I am not sure why you feel you don't have access/control over the Html? The goal of the SafeLoader is that you dont care what the html is, you simply try and "output" the control (within the "bubble") and determine if it loads OK in its current state.
If it does (i.e. the html is returned) then you can do what you like with it, output the html, add the control to the controls collection, whatever!
If not, then again, you can do what you like, render an error message, throw a custom exception.. The choice is yours!
I hope this helps clarify things for you, if not, then please shout :)
I used #Keith's approach, but the problem is that the control is rendered up until the Exception is thrown, potentially resulting in open HTML tags. I'm also rendering the exception information in the Control if in Debug mode.
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
try
{
// Render the module to a local a temporary writer so that if an Exception occurs
// the control is not halfway rendered - "it is all or nothing" proposition
System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
base.Render(htw);
// We made it! Copy the Control Render over
writer.Write(sw.GetStringBuilder().ToString());
}
catch (System.Exception ex)
{
string message = string.Format("Error Rendering Control {0}\n", ID);
Log.Error(message, ex);
if (Page.IsDebug)
writer.Write(string.Format("{0}<br>Exception:<br><pre>{1}\n{2}</pre>", message, ex.Message, ex.StackTrace));
}
}