[ModalDialog][view models / page structuring series] overflow hidden not removed from body after closing modal

This is weird because it started happening after I already dealt with multiple modals, even nested ones. It manifests in both Chrome and Edge.

Code and structure got complicated now and I’m not currently able to explain this scenario completely but I try.

VM of MarkupControl1 with modal (GuardModal) that acts as guard to a Button named CancelOpButton.
Another Button, OpenOpPopupButton in the same VM opens a modal with validated fields inside (PopupModal inside MarkupControl2 - child of MarkupControl1), triggered by SaveOpButton which also opens a ConfirmModal that has YesButton. YesButton postbacks and the server does the operation. When op is completed, a SuccessModal is shown (opened on the server) that has OKButton that closes SuccessModal and its parent, PopupModal

In the picture, OperationSuccededModal = SuccessModal (because I need to use short names to explain all this).

The problem appears only when, after hitting OKButton and SuccessModal & PopupModal are now both closed and I am returned to see MarkupControl1, I hit CancelOpButton and GuardModal appears, putting overflow: hidden on body. So far so good.
But regardless of how I close this GuardModal, it closes and I am left with a page that has no scrollbar and scroll from mouse does not work (and the page is long… gridViews and stuff). Inspecting the page, I see that overflow: hidden is still there on the body. I found a hack solution on the www but it enforces the scrollbar always. I think to write some JS but I also thought maybe I’m doing something wrong here with opening and closing modals.

If instead I open and close the modals without opening SuccessModal, all is well.
Also, after the overflow is stuck on hidden, any PostBack from MarkupControl1 or MarkupControl2 buttons does not make it go away.

Any idea?


Switching it to handler style does not cut it:



It’s all about the _parent.Close():

In spite of its name, “ModalDialogViewModelBase” is not only for VMs of ModalDialog control. It is inherited by the VM of the MarkupControl2(MC2) that hosts the PopupModal (which does not have a VM of its own, uses properties from the MC2 VM).

To the custom event OnClose subscribes the parent MC1 that holds the instance of the MC2, called OperationInstance.

And I pinpointed the source of the problem: making OperationInstance null as to respect the structural model of nullifying VMs of the sections I close.

Again, OperationInstance is not the VM of the ModalDialog control, but the VM of the MarkupControl2 which hosts ModalDialog and when .Close() is called on OperationInstance, the ModalDialog should in theory close correctly as it has its IsDisplayed property bound by the OperationInstance’s IsOpen which you can see in the picture with the ModalDialogViewModelBase (which you can see as being Base for Popup MarkupControl… but is named like this because it applies also to ModalDialog VMs… :joy:)

I would try my best to not yet again restructure through the whole thing, now just for working to nullify the VM of the ModalDialog instead of the VM of the container MarkupControl itself (like it is now).

Picture from the awesome MarkupControl1 (parent of all this hullabaloo):

<popup:Operation is MarkupControl2 (the child)

mdConfirmationForCancelCurrentOperationRequest is the GuardModal from earlier post in this thread.

Something is clearly not right here and I cannot see it.

I have restructured by eliminating my badly named custom event “OnClosed” and going properly (I hope) with using Closed event on the Modals. Also switched from nullifying the VM of MarkupControl2 to creating VM for the PopupModal ModalDialog inside MarkupControl2 and setting this one to null after closing.

Same as in the previous structuring, where I was setting to null the VM of the MarkupControl2, the culprit is setting the VM to null, see code line 411 below.
The sticky overflow:hidden now happens in two cases instead of one:
a) after clicking custom btn OK on SuccessModal’s footer;
b) and after hitting escape key on SuccessModal and then opening and closing CancelModal (by both custom btn in footer and the escape key).

Also tried to set PopupModal to null later, at PreRender(). Same, no results.


PopupModal (sibling of SuccesModal in markup and in VM hierarchy):

The modals’ properties and commands:

I ran out of options and I am forced to use a workaround until further clarifications, to move dev forward.

I’m sorry, I’m getting lost in this and I don’t know how to reproduce the issue. Could you please try to reproduce the same problem in simpler context?

To workaround it simply I think you can try

  • Setting the DataContext only inside the Modal. The DataContext on modal works for me, but I can image it might break it in some more complex context.
  • Add this hack Context.ResourceManager.AddInlineScript("document.body.style.overflow=''"); to your closing command, it will remove the style

option 1 does not cut it, it seems.
option 2 does not scale well in my scenario

I used this nasty workaround in dotvvm.events.postbackViewModelUpdated handler:

Until now it works but I don’t count on it yet…

Ok, this is reasonable. It would still be great to fix the issue, it is quite clearly a bug in the ModalDialog, I just don’t know how to reproduce it

I confirm that, after repairing the other internal issue I had with repeating Load() on the ModalDialog VM (see [page lifecycle series] repeating Load() for view model of ModalDialog on the same PostBack),

the issue here still manifests

I’m forced to return to this issue

And I will have to see if your hack applies well, because after restructuring and fixing the repeating Load() issue, if I close the popup without going all the way and submit the data and then reopen it, I get this exception:

Because of this, I must go the way of setting PopupModal to null on server-side.

It keeps throwing this even if I comment out all the [Protect(ProtectMode.EncryptData)] from the entire project. So this makes no sense.

The SecurityException message could be more destriptive… When it fails in AssertEnd, it most likely means that it received some encrypted properties which did not get deserialized. It will for example happen if you remove collection elements client-side, or null-out some object with encrypted values.

This prevents some forms of data manipulation attacks, with this check the attacker cannot simply remove the encrypted value by nulling-out its parent.

ProtectMode.SignData is essentially the same thing. The value is also visible client-side, but it behaves the same during deserialisation.

I understand.
So if this is the case and PopupModal VM contains [Protect]-ed properties in various places, the workaround with setting VM to null on client-side is no longer an option.

I managed to adapt your suggestion into a working workaround:

What I have to say about it is that, at least in the context I have here, Context.ResourceManager.AddInlineScript() din not succeed because somewhere later in the lifecycle the overflow style gets overwritten somehow.

The context being: the server-side command handler of a bp:Button in the ModalDialog’s footer.