views:

2016

answers:

4

Say you have something like an ASP.NET ASP:DetailsView to show and edit a single record in a database.

It's simple to record the error cases... you add validation and a validation summary. When your update form fails validation it naturally makes noise: it shows the validation message and/or the validation summary. Not a single code behind is required.

But then, you pass validation, and it makes your update completely silently. There's no sense that anything happened, and there doesn't seem to be any default settings to make a success message without code-behinds.

But, even code-behinds are confusing. What event should show the success message? onItemUpdate, right? Fine, but then let's say you make another change and get a validation error? Your success message stays. I wasn't able to find an event that would reliably turn off an existing success message if there were a validation error.

This should be web development 101! Why is it so hard?

EDIT:

Someone suggested using the ItemCommand event... I tried this and many other events, but that success message just won't disappear. Here's some code.

My message in ASP.NET

<label id="successMessage" class="successMessage" runat="server"></label>

And my DataView tag (simplified):

    <asp:DetailsView 
        Id="EditClient"
        DataKeyNames="LicenseID" 
    DataSourceID="MySource"
    runat="server" 
        OnItemUpdated="SuccessfulClientUpdate"
        OnItemCommand="ClearMessages">

And, my code-behind:

protected void SuccessfulClientUpdate(object sender, DetailsViewUpdatedEventArgs e)
{
    successMessage.InnerText = string.Format("Your changes were saved.");
    successMessage.Visible = true;
}

protected void ClearMessages(object sender, DetailsViewCommandEventArgs e)
{
    successMessage.InnerText = string.Empty;
    successMessage.Visible = false;
}

Once I do a successful update, however, nothing seems to make that message disappear, not even failed validation.

2nd EDIT:

Just want to be clear that I did try putting the ClearMessages code in Page_Load. However, nothing seems to make that successMessage label disappear when I hit update a 2nd time WITH a validation error. Can anyone suggest any other troubleshooting tips?

+1  A: 

Use the ItemCommand event and perform reset to clean state for every command that is given. Then if validation fails on update, the validation error will be displayed. If it succeeds, it will show the success message. Subsequent, button clicks will invoke the ItemCommand event and you can reset again to start fresh.

tvanfosson
I did try this, but it doesn't seem to actually make the label invisible on a 2nd try at editing that triggers a validation failure.
danieltalsky
Do you have client-side validation enabled? If so , then you'll need to hide the success message with javascript.
tvanfosson
A: 

Why not turn the validation message off in the Page_Load. I assume that if a post back occurs you'd want to get rid of the message so make sure it's always off. Or disable view state for the control by setting EnableViewState="False" in the markup (aspx page).

So:

protected void ClearMessages(object sender, DetailsViewCommandEventArgs e)
{
    successMessage.InnerText = string.Empty;    
    successMessage.Visible = false;
}

becomes:

protected void Page_Load(object sender, EventArgs e)
{
    successMessage.InnerText = string.Empty;    
    successMessage.Visible = false;

}

Also as a side note if you buiding .net sites you need to get comftorble with code behinds IMHO:-)

JoshBerke
I'm fully comfortable with code-behinds, but this is a very simple web application, and I made a design decision to do as much as I possibly could using native ASP.NET tags. It's lovely, and honestly I haven't had to write a lick of code-behind before this.
danieltalsky
And, sadly, that doesn't do the job. When I trigger my validation message, the success message stays. I even did try turning EnableViewState off.
danieltalsky
+3  A: 

As far as I know, there is no native way of doing this. You may rant about it, maybe Microsoft will hear it :).

Resetting the "success message" on Page_Load, or wherever in your code-behind, won't work. This is because ASP.NET validation is usually done both client and server-side. This means for every validation control you put on the page, ASP.NET generates some client-side Javascript that does the validation and renders the error on the client, without going back to the server. So you're stuck with both the success message and the error message at the same time.

What you can do about it:

  • place a <div> control on your page, that would show up the success message (as already suggested by others above). Whenever you update something (in server-side code), show up the control and set a meaningful "Successful!" message text.
  • register a custom Javascript function that would lookup the <div> and hide it on every page submit. Be aware that the function needs to be called before the autogenerated client script that does the validation.

If you look at the client source of an ASP.NET page (with validators on it), here's what you can find:

<form name="aspnetForm" method="post" action="MyPage.aspx" onsubmit="javascript:return WebForm_OnSubmit();id="aspnetForm">

The WebForm_OnSubmit is generated by ASP.NET and calls the javascript that does the validation. Sample:

function WebForm_OnSubmit() {
if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
 return false;
return true;
}

To register your custom code that hides the success message, you should place (in your code-behind) something along these lines:

if (!Page.ClientScript.IsOnSubmitStatementRegistered("ClearMessage"))
{
 string script = @"document.getElementById('" + 
  yourDivControl.ClientID + "').style.display='none'";
 Page.ClientScript.RegisterOnSubmitStatement(Page.GetType(), "ClearMessage", script);
}

This will turn your page's autogenerated WebForm_OnSubmit into the following:

function WebForm_OnSubmit() {
 document.getElementById('ctl00_yourDivControl').style.display='none';
 if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
  return false;
 return true;
}

The effect: On every postback (e.g. when ItemCommand is triggered, or when some Save button is clicked, or anything else), you will show up the div control with the "success" message. On the next postback, just before submitting the page to the server, this message is cleared. Of course, if this postback also triggers a "success", the message is shown again by the code-behind on the server. And so on and so forth.

I hope the above is helpful. It's not the full-blown solution, but it gives sufficient hints to point you in the right direction.

Dan C.
Holy crap, that is a lamer reality than I could have ever imagined, but a fantastic answer. I assume I could also force validation to go back to the server every time. You're a champ.
danieltalsky
Another hint that could be useful: you can do all the above stuff in your master page (assuming you use ASP.NET 2.0). That is, you can place the div control right above the content, and display the info messages there (continued...)
Dan C.
You expose a SetMessage() public method in the MasterPage-derived object and you get the "info message" support for all pages that use this master page, by using `((MyMaster)Page.Master).SetMessage("Success")`;
Dan C.
+1  A: 

Daniel, I needed something similar so I derived from a Label and bound it directly to the events raised by the various DataSourceControl derivatives (LinqDataSource, ObjectDataSource, SqlDataSource). I also used client-side JavaScript to hide the label during validation and/or form submission (like Dan.C's answer).

The control exposes separate message text properties for successful Deleted, Inserted and Updated events.

I've published the commented source for the solution at http://codehq.net/files/UpdateSuccessMessage.zip

Hope this helps.

devstuff
Thank you for your answer. I'm downloading the code and reviewing it. I still never ended up implementing something but my users are starting to ask for this. I was planning on some kind of jQuery "fadeout" solution, but I am checking yours.
danieltalsky