c# asp.net response.write shrinks text boxes - c#

I have a Web Form project I am developing C# ASP.Net 4.5. I have a class that calls a response.write to display a message for user input validation purposes. The call to response.write is made inside the class in a method from creating a new instance of the class, thus the class method, by pressing a button on the form. But using the response.write causes the textboxes on my page to shrink considerably. Then when I press a different button the textboxes go back to normal. It only happens when I use response.write. Any help would be appreciated. Code call in class method:
HttpContext.Current.Response.Write("File not found");

By using that you're simply dumping text to the top of the page, typically outside of the <html> tags. This can have a knock-on effect to the rest of the pages style; i see the same when i am spitting out test responses.
Instead, put yourself a label control on your page and populate that instead. you can put it exactly where you want and simply call:
So put this: <asp:Label runat="Server" id="myLabel" /> where you want the message to appear.
Then in your code-behind, write this. It will populate the label with the given text.
myLabel.Text = "File not found";
The Label control will be rendered as a <span></span> - so styling it is nice and easy.
If you fancied using a <div> then use the Panel control.
If you're not fussed about any sort of style, go for a Literal control, which renders no html elements.

When you use the HttpContext.Current.Response.Write on code behind is direct send to the page your text, at any random point of page render.
Maybe on top, maybe on bottom, on some point that you can not control if you use the code behind to call it.
Change the way you show your message, at a minimum you can use a literal control to render there your output and show it.

You may want to use a control to display your error. For example:
In the aspx/ascx
<asp:Label id="ErrorMessage" runat="server" />
in the page/control code behind
//call TheClass
TheClass c = new TheClass();
string error = c.TheMethod();
if (!string.IsNullOrEmpty(error))
{
ErrorMessage.Text = error;
}
in TheClass
public class TheClass
{
public string TheMethod()
{
string result = "";
...
//When file is not found
result = "File not found";
...
return result;
}
}

Related

Find Control in code behind - multiple results controls - nth occurence

I have the following problem.
I have a asp:textbox on the page, runat server with an id of say txt
This text box is in a <div>, nothing special. ie:
<div>
<asp:TextBox id="txt" runat="server"></asp:TextBox>
</div>
The problem is there is some java script which when you push the corresponding button it doubles (copies) the div. This is by design. It is meant to.
When you hit save but at the bottom of the page on a asp:Button, it can't find the value I need because it returns two results.
In the code behind:
(Textbox) blah = (Textbox)senderbutton.FindControl("txt");
string test = blah.text
But the result is essentially--> "The value in the textbox , The value in the textbox"
I.e. it is there twice. I have worked around this by doing the following:
string[] test = blah.text.split(new[] { ',' })
and then only calling the second value in the array or whatever.
BUT, now I have this situation but the problem is that a user can enter a string with a ' , ' in it, hence the splitting goes to crap....
So can I find a control with an id, but only find the nth occurence of it in the code behind?
Seems you need to give different name(like txt0,txt1...) for each copy of the input controls.
You can do this using javascript up on client click(prior to form submission) of your asp button
-- Javascript method
function ModifyName() {
var x = 0;
$("input[name='txt']").each(function () {
$(this).attr("name", $(this).attr("name") + x);
x++;
});
}
-- asp:Button
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
OnClientClick="ModifyName();" onclick="btnSubmit_Click" />
So in code behind you can get the values like this...
protected void btnSubmit_Click(object sender, EventArgs e)
{
var resultArr = Request.Form.AllKeys.Where(x => x.Contains("txt"))
.Select(x => Request.Form[x]).ToArray();
}
Not a very nice solution, but you could examine the Request.Form collection directly upon postback and write some code to process your dynamically added textbox fields.
The best solution would be: avoiding copying the div in js. Since you said "This is by design. It is meant to."(even I really doubt it), there are some alternative solutions:
(1) Don't use the default submit behavior of the form. That is, in the click (js) event of the save button, organize the data in the form and then submit it.
(2) Modify the second(copied) textbox's id so that its id is different from the original one, and then get the data in code behind.
I am not sure why you using FindControl method to find the control when you can directly access the txt control from code behind.
You can get results easily
String test = txt.Text;

C# Script output in aspx page

I am having issues with the output of my C# script embedded in my asp.net code. The output is generated after clicking a submit button for a web form. This web form is at the top of the page. The output, when clicking submit, is currently being placed above the web form which is in turn pushing the web form underneath it. I would like the opposite to happen. I want it to output below my web form. The way I generate output from my script is as follows:
Response.Write("<p>");
foreach(obj in arr){
Response.Write(obj);
}
Response.Write("</p>");
Also if it matters, I initialize the script with runat="server". The script gets called when the user selects "submit" near the web form. Thanks in advance. I've been trying to format this thing for quite some time now.
You would be better off putting a 'literal' object in the place on your page precisely where where you want the result to appear, and then, instead of spitting out HTML with response.write, you assign the desired text to the literal in your code-behind.
Like this:
<html>
<p>
<asp:Literal ID="ltlTest" runat="server"></asp:Literal>
</p>
</html>
and then in your code behind:
ltlTest.Text = "the string you want to show...";
You can include html tags in the string assignment, though generally I try not to.
You've got some choices.
You can make arr a public property, and then use <% foreach (var obj in arr) Response.Write(obj); %> directly in the page markup where you want it.
You can put in an <asp:Literal runat="server" ID="Literal1"> control and then set Literal1.Text = ... in your code. This achieves the same, but with ViewState (so the value is persisted on postbacks).
If you'd like the result to be rendered within <span /> tags, you can use an <asp:Label /> control. This is usually the best choice for displaying messages to the user.

Ajax AsyncFileUpload fires server code but does not update client web page

I have an asyncfileupload control inside an update panel. The file succesfully upload and fires the correct server side code. The code on the server is exected as expected however, one line in the server code changes the text on a label. I step through the code in debug mode and the line is executed but no change is made to the page.
Here's some of the code:
<asp:UpdatePanel runat="server" ID="updater" >
<ContentTemplate>
<asp:AsyncFileUpload ID="fileUpload" runat="server" OnUploadedComplete="FileUploadComplete" />
<asp:Label ID="AsyncText" runat="server" Text="File Type not checked" />
</ContentTemplate>
</asp:UpdatePanel>
public void FileUploadComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
System.Threading.Thread.Sleep(500);
if(fileUpload.HasFile) { AsyncText.Text = "file of correct format: "; }
}
Can anyone help me with solving this problem or offering annother solution??
Thanks
I think you are going to have to move toward a different solution. From your label message, it looks like you are trying to check the file type, correct? Basically, the AsyncUplaod control, although posting back to get the uploaded file to the browser, is not actually updating the page's viewstate, thus the label never gets updated. Boo! I was able to visualize this using this code in the page load event.
if (Page.IsPostBack)
{
if (Request.Files.Count > 0)
{
AsyncText.Text = "file of correct format";
ListItem item = new ListItem("item to add");
lb.Items.Add(item);
}
}
This was allowing me to set the label text but still nothing changed until I clicked on a random button that I added to the page. This button didnt even have an event in the code behind, but it was enough to cause a normal postback, and the label text and list item were successfully updated/added to the list. With that said, I would wait to update any labels until the user clicks upload by using a seperate upload button. (ie use the AsyFileUplaod to get it to the browser, but another button to save the file to the server). You can always do file evaluations in the button click event by referencing the posted files to the webpage as I did in the code above.
Some other examples I found online were using javascript to change the label text which works well also. Somthing like this:
string message = "";
if (e.StatusMessage == "Success")
{
message = "File upload successful;";
}
else
{
message = "File did not upload successfully;";
}
ClientScript.RegisterStartupScript(this.GetType(), "akey", "document.getElementByID('label').value =" + message, true);
Another example: here
I think in this case it's just the nature of the control and the only way to achieve what you want is though some creative thinking. If you have any other questions about anything I listed here feel free to ask.
Good luck!
Where is the label positioned, inside or outside the update panel? Seems like the partial page update may not be including the update to the label text. I would say move the label around as the simplest suggestion, but you could also try something like RegisterStartupScript which will change the lable text via javascript. This should still give you server side control over what text to display based on what happens during the upload.
If you could post some code that would be great.

Creating and showing dynamic error messages (Not working inside UpdatePanel)

My web forms inherits a class called MyPageMain, which inhertis System.Web.UI.Page and is located on the App_Code folder.
In this MyPageMain class I created this method, to record and output Exceptions (error messages):
public string Error(Exception pException, string pFriendlyMessage)
{
using (BusError erro = new BusError())
{
int? errorId = //HERE Routine to log the error;
StringWriter stringWriter = new StringWriter();
using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "erroMain");
writer.RenderBeginTag(HtmlTextWriterTag.Div); //<div>
writer.RenderBeginTag(HtmlTextWriterTag.P); //<p>
writer.Write(pFriendlyMessage);
writer.RenderEndTag(); // </p>
writer.RenderBeginTag(HtmlTextWriterTag.Small);
writer.Write("Event tracker:");
writer.Write(errorId);
writer.RenderEndTag();
writer.RenderEndTag(); // </div>
Console.WriteLine(stringWriter.ToString());
}
}
}
Then, when there is some exception on the page, I call it, like this:
Protected void btnLoad_Click(object sender, EventArgs e)
{
LoadData();
}
private void LoadData()
{
try
{
//Loading some data here.
}
catch (Exception ex)
{
Error(ex, "Unexpected error trying to load data.");
}
}
This is bulding OK, but doesn't work... I think that one of the reasons may be the fact that the whole thing is inside an UpdatePanel. Any suggestions on how to make this work?
Is this Console.Writeline suitable for what i'm trying to do? Is this going to work on UpdatePanels?
Already Tried with Response.Write(...) and it does work. But not inside an UpdatePanel
When you use an UpdatePanel, you can only update content within the panel during an async postback triggered from that panel, so your error message will have to appear somewhere within the UpdatePanel. (That is, unless you set UpdateMode="Always" on one of your UpdatePanels, then its content is updated on every async and full postback. But that doesn't help you here unless you put your error message in its own UpdatePanel with UpdateMode="Always", which would require you to add said UpdatePanel to every page. I understand this is not what you want to do.)
The following example will work to add the error message at the top of the UpdatePanel.
You will need to add a Control errorParent parameter to your Error method, so it can add the error message as child control to that parent control.
In your catch block, just pass in whatever container control where you want the error message to appear. That control must be a container to accept child controls, so it has to be something that renders as a <div> or <span> tag, like an asp:Panel or asp:UpdatePanel.
In the example below, you could use errorParent.Controls.Add(errorControl) to show the error message at the bottom of the UpdatePanel, or use AddAt() with a different index. Just be sure that index will always work on every page.
Take a parent control and add a new Literal child control:
public string Error(Exception pException, string pFriendlyMessage, Control errorParent)
{
using (BusError erro = new BusError())
{
int? errorId = //HERE Routine to log the error;
Literal errorControl = new Literal();
errorControl.Text = String.Format("<div class=\"errorMain\"><p>{0}</p><small>Event Tracker: {1}</small></div>", pFriendlyMessage, errorId);
errorParent.Controls.AddAt(0, errorControl);
}
}
Pass in the parent control:
private void LoadData()
{
try
{
//Loading some data here.
}
catch (Exception ex)
{
Error(ex, "Unexpected error trying to load data.", MyUpdatePanel.ContentTemplateContainer);
}
}
Since your Error method returns string, you can return error message and display it.
Place Literal in your UpdatePanel (maybe in MasterPage, so you do not have to write it for all 40 or more pages). When exception is thrown, handle it with your Error method and set returned message to Literal.
Console.WriteLine is not usable in ASP.NET. Use Debug.WriteLine instead. It will write to Output window in VisualStudio.
Many of the answers are dancing around the issue. Console.WriteLine is a command used to output a line of text for a Console application (command-line). This is a Web app. So, you either use Response.Write to spit a string out to the Response stream or set the text of a Literal control that is already on the page and set it to be visible (default hidden).
Since I myself completely missed the UpdatePanel detail, here's an alternate solution to make up for it. My example uses a hidden div and some jQuery through the usage of the ScriptManager control to inject text into a div that is outside the UpdatePanel. Based on the conditions of the go_Click handler method of the button, it'll show or hide an error message using jQuery that gets injected into the Page server-side at the time of the UpdatePanel's update.
Note that it is critically important to use the ScriptManager's functions to register JavaScript rather than Page.ClientScript when using AJAX. Using the latter won't add the JS to the page.
Page markup
<div id="errorMessagePlaceHolder" class="error" style="display:none;">
</div>
<asp:UpdatePanel ID="myPanel" runat="server">
<ContentTemplate>
<asp:TextBox ID="myText" runat="server" />
<asp:Button ID="go" Text="GO" runat="server" OnClick="go_Click" />
</ContentTemplate>
</asp:UpdatePanel>
Page code-behind
public partial class _Default : Page {
protected void go_Click(object sender, EventArgs e) {
try {
// Do something that can throw an exception
// Hide the error if we reach the end as we may have triggered
// it in a prior update and no longer want it to display.
HideError();
} catch (Exception) {
ShowError("myText is empty!");
}
}
#region Move to a base page or a helper class if it helps reduce duplication
private void HideError() {
ScriptManager.RegisterStartupScript(Page, GetType(), "HideErrorMessageScript", HideErrorMessageScript(), true);
}
private void ShowError(string errorMessage) {
ScriptManager.RegisterStartupScript(Page, GetType(), "ErrorMessageScript", ErrorMessageScript(errorMessage), true);
}
private static string HideErrorMessageScript() {
return #"
$(document).ready(function() {
$('#errorMessagePlaceHolder').hide();
});
";
}
private static string ErrorMessageScript(string errorMessage) {
return
string.Format(
#"
$(document).ready(function() {{
$('#errorMessagePlaceHolder').html('{0}');
$('#errorMessagePlaceHolder').show();
}});
",
errorMessage);
}
#endregion
}
I feel like nobody has actually answered the entire question yet, so let me try.
Is this Console.Writeline suitable for what i'm trying to do?
Probably not, unless you just want debug information to appear in the output window while debugging. Some people like to keep outputting info to the Console, even in a release build and so if you want to do that with your errors, it's a valid choice, but you should also be showing a friendly error message to the user and/or logging the error to some kind of persistence (eg. log file). All of the answers above are suggesting ways for you to show some notification of the error to the user.
Is this going to work on UpdatePanels?
There is NO reason why it shouldn't if your triggers and the like are set up properly (and we know they are because you said that you're able to hit the Console.WriteLine breakpoint). I wonder if your Console output is working fine but you're looking for it in the wrong place? In the typical configuration for a web application, it should appear in the Output window of the Visual Studio instance you're using to Debug.
As to a suggestion for what I think you're asking, which is "how do I get my error message to appear in the update panel if there's an error loading the content for that update panel?"...
I would suggest an approach similar to nekno's proposal above. You can either dynamically add a control whose text you can set to be the error string during update panel request processing or you can even have an initially hidden/collapsed control on the page, which is only set to be visible in the case of an error. I'd prefer the latter approach because it's more maintainable. You can completely control the look and feel of the error label from the markup/display views of your ASPX page.
Are you calling .update() on your UpdatePanel after your LoadData() method runs? I think the UpdatePanel won't automatically fire unless the postback originates from inside it.
Ex:
Protected void btnLoad_Click(object sender, EventArgs e)
{
LoadData();
MyUpdatePanel.Update();
}
Update: I was able to get Response.Write() to work in an UpdatePanel by registering a trigger like this <Triggers><asp:PostBackTrigger ControlID="btn1" /></Triggers> for the button that will create the error.
Are you trying to log errors or display them? If you are trying to display them, you should:
On your masterpage, create a spot where your errors will be displayed (maybe below your navigation bar or near the bottom:
<asp:ContentPlaceHolder id='cphError'></asp:ContentPlaceHolder>
Everytime you get an error, you can call your error function as is, but instead of writing out the text with Response.Write() or Console.WriteLine(), you can add a label in there:
Label lError = new Label();
lError.CssClass = '..';
lError.Text = '..';
cphError.Controls.Add(lError);
This will help you out with displaying the error, but AJAX will still be a problem. At this point, you have two options:
Since update panels update other update panels, you can wrap an update panel around cphError, this way your AJAX calls will still update that area
OR: You can can use ClientScript.RegisterStartupScript to create the error label. (This method is only preferable if you do not have a static error message spot)
Place a Panel on the master, extend it with the modalpopupextender in the AjaxToolKit. When the error is raised, write the contents of string writer to a label in the panel E.g. Label lbl = (Label)Master.FindControl()
lbl.text = StringWriter.ToString();
// Now access the modal popup
AjaxControlToolkit.ModalPopupExtender MPE = (AjaxControlToolkit.ModalPopupExtender)Master.findControl("");
// and show it
MPE.Show();
The Modal will need a hidden button to use as it's target control, but it will not require a user's input. I accomplish this on the page with the following code:
<asp:Button ID="btnDummyOK" runat="server" Style="display: none;" />
<asp:ModalPopupExtender ID="mpePnlErrors" runat="server" TargetControlID="btnDummyButton" PopupControlID="pnlErrirs" BackgroundCssClass="modalBackground" CancelControlID="btnCancel" OkControlID="btnOK" />
Good luck
I think Console.WriteLine don''t work on asp.net application and i think inside an update panel you can simple fire the throw New Exception( the friendly error message) and it will appear in an alert box.

ASP.Net: User control with content area, it's clearly possible but I need some details

I have seen two suggestions for my original question about whether it is possible to define a content area inside a user control and there are some helpful suggestions i.e.
Passing in content to ASP.NET user control
and
ASP.NET User Control inner content
Now, I like the theory of the latter better than the former just for aesthetic reasons. It seems to make more sense to me but the example given uses two variables content and templateContent that the answerer has not defined in their example code. Without these details I have found that the example does not work. I guess they are properties of the control? Or some such?
EDIT - DETAILS: What I am trying to do
I have need of an ASP.Net user control that conceals some content in a panel inside a placeholder and asks for the input of a code in a visible panel.
Essentially the user will put their code into the provided textbox in Panel A and submit it, it will be checked and, if it is valid, panel B and the locked content will be displayed.
I have done a test where the content was hard coded into panel B but as soon as I need to make the content a generic input it fails. If it were just text or somesuch then I could make it a property of the control, but as it is, in fact, another User Control I am having some difficulty getting this into the "hidden" panel.
Any other workable solutions are also welcome.
EDIT NOTE: The solution I'm trying to implement this in 2.0 I did find a 3.5 solution which I cannot use.
The former example seems workable but I'd prefer to go with the latter if someone could fill in the blanks for me.
Thanks.
Okay, so this is disturbingly easy but many of the tutorials on the web that talk about this kind of thing push to do extravagant things that require the control to parse ListItems or such.
So this solution is purely so that you can build a control that, for whatever reason, has a placeholder in it that could have anything inside it (kind of like a content area on a Master page). In this instance it happens to be because the Panel containing the placeholder is hidden until appropriate input actions have taken place in another panel.
First, you need to add this:
[ParseChildren(true,"Content")]
[PersistChildren(false)]
just above the part of the control which looks like this:
public partial class MyControl : System.Web.UI.UserControl
then in the control scoped declarations at the head of the control you want to declare thus:
private Control _content;
[PersistenceMode(PersistenceMode.InnerProperty)]
public Control Content { get { return _content; } set { _content = value; } }
Finally you need to place the content into the placeholder like this:
phContent.Controls.Add((Control)_content);
That last line goes into the Page_Init event. For reference "phContent" is the name of the place holder where you want the content to appear, like this:
<asp:Panel ID="pnlLockable" runat="server" Visible="False">
<asp:Placeholder runat="server" ID="phContent" />
</asp:Panel>
On the front end the resulting implementation looks like this:
<uc:MyControl runat="server" ID="lockit1">
<Content>
//...your stuff goes here...
</Content>
<uc:MyControl>
Note that I presume that what is inbetween the Content Tags is a root control. This is because I nested another user control in there. I imagine if you put whatever content you want within a panel or placeholder it should be fine.
Also you can read "How to: Create Templated ASP.NET User Controls". Really helpful.

Categories

Resources