This is a migrated thread and some comments may be shown as answers.

[Solved] Window losing modal state on post back

14 Answers 233 Views
Window
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Donna Stewart
Top achievements
Rank 1
Donna Stewart asked on 15 Feb 2011, 11:12 PM

I have a window that I use for user log in.  I have a submit button in the partial view that loads in the window. This posts back to the server to validate the login.  If there is an error, I would like for it to come back to the window and show the error and let the user correct.  However, the partial view is being loaded into the browser main window.  I looked at this post - Window Loses Modal State Upon Validation Errors - but it suggests doing client-side validation.  I can't do that here.  Please let me know how to accomplish this.  Thank so much for all of your help.  My code follows:

Site.Master where the window is defined:

<%@ Master Language="VB" Inherits="System.Web.Mvc.ViewMasterPage" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  
<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <script src="<%= Url.Content("~/Scripts/jquery-1.4.3.min.js") %>" type="text/javascript"></script>
    <script src="<%= Url.Content("~/Scripts/jquery-ui-1.8.5.custom.min.js") %>" type="text/javascript"></script>
    <script src="<%= Url.Content("~/Scripts/ui.dropdownchecklist-1.2qa-min.js") %>" type="text/javascript"></script>
    <script src="<%= Url.Content("~/Scripts/jquery.json-2.2.js") %>" type="text/javascript"></script>
</head>
<body>
    <%= Html.Telerik().StyleSheetRegistrar() _
                                            .DefaultGroup(Function(group) group.Add("telerik.common.min.css")) _
                                            .DefaultGroup(Function(group) group.Add("Site.css")) _
                                            .DefaultGroup(Function(group) group.Add("ui.dropdownchecklist.standalone.css")) _
                                            .DefaultGroup(Function(group) group.Add("telerik.windows7.min.css")) _
                                            .DefaultGroup(Function(group) group.Add("jquery.fastconfirm.css"))
     %>
   <form id="form1" runat="server">
    <div id="container">
        <asp:ContentPlaceHolder ID="MainContent" runat="server" />
        <div id="footer">
            Copyright 2010 Green Mountain Consulting, All Rights Reserved    
            <img alt="mountains" src="<%= Url.Content("~/Content/Images/ClassicSiteIcon.png") %>" style="float:none"/>    
            <a class="greenlink" href="">Privacy Policy</a>
        </div>
  
    <div>
        <%  Html.Telerik().Window().Name("LogOnWindow") _
        .LoadContentFrom("LogOn", "Account") _
        .Buttons(Function(buttons) buttons.Refresh().Maximize().Close()) _
        .Draggable(True) _
        .Height(575) _
        .Width(550) _
        .Resizable() _
        .Title("Log In") _
        .Visible(False) _
        .Render()
            %>
    </div>
    </div>
    <%= Html.Telerik.ScriptRegistrar().jQuery(False).DefaultGroup(Function(addGroup) addGroup.Add("telerik.common.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.combobox.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.list.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.treeview.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.grid.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.calendar.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("telerik.datepicker.min.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("jquery.cascadingDropDown.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("jquery.fastconfirm.js")) _
                                                                                                    .DefaultGroup(Function(addGroup) addGroup.Add("jquery.cookie.js")) _
                                        .OnDocumentReady("$('#login').bind('click', function openWindow(e){ $('#LogOnWindow').data('tWindow').center().open().refresh();})")
     %>
  
   </form>
</body>
</html>

The logon.ascx
<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of GMC_Hub_and_Spoke.LogOnModel)" %>
    <script type="text/javascript" language="javascript">
        $(document).ready(
            function () {
                $('input.focus').attr('value', ''); setTimeout(function () {
                    $(".focus").focus();
                }, 500);
  
            }
        );
  
    </script>
    <% Using Html.BeginForm() %>
    <div id="publicpage">
           <p><img alt="GMC Logo" src="<%= Url.Content("~/Content/Images/GMC-Logo-100-x-76.jpg") %>" /><span class="publiccontentheader" style="padding-left:15px">GMC Log In</span></p>
                <div id="loginmain">
                    <p class="homecontentheader">Log In</p>
                    <div id="customerField"><p>
                            <%: Html.LabelFor(Function(m) m.CompanyCode)%> 
                            <%: Html.TextBoxFor(Function(m) m.CompanyCode, New With {.class = "focus"})%>
                            <%: Html.ValidationMessageFor(Function(m) m.CompanyCode)%>
                            </p>
                    </div
                    <p>
                        <%: Html.LabelFor(Function(m) m.UserName) %> 
                        <%: Html.TextBoxFor(Function(m) m.UserName) %>
                        <%: Html.ValidationMessageFor(Function(m) m.UserName) %>
                    </p>
                    <p>
                        <%: Html.LabelFor(Function(m) m.Password) %>
                        <%: Html.PasswordFor(Function(m) m.Password) %>
                        <%: Html.ValidationMessageFor(Function(m) m.Password) %>
                    </p>
                    <p>
                        <%: Html.CheckBoxFor(Function(m) m.RememberMe) %>
                        <%: Html.LabelFor(Function(m) m.RememberMe) %>
                    </p>
                    <p>
                        <input type="submit" value="Log On" />
                        <%: Html.ValidationSummary(True, "Login was unsuccessful. Please correct the errors and try again.")%>
                    </p>
                </div>
        </div>
    <% End Using %>

The controller code:
Public Function LogOn() As ActionResult
    Dim logOnModel As New LogOnModel
    logOnModel.carrierList = New List(Of SelectListItem)
    logOnModel.carrierList = DictionaryToSelectList(Session("carrierList"))
    Return PartialView(logOnModel)
End Function
<HttpPost()> _
Public Function LogOn(ByVal model As LogOnModel, ByVal returnUrl As String) As ActionResult
    If ModelState.IsValid Then
        Dim userInfo As New PersistentUserInfo
        Dim companyCodeToUse As Integer
        Dim membershipService As New GMCMembershipProvider
        If model.CustCarrierFlag Then
            companyCodeToUse = model.CarrierCode
        Else
            companyCodeToUse = model.CompanyCode
        End If
        model.carrierList = New List(Of SelectListItem)
        model.carrierList = DictionaryToSelectList(Session("carrierList"))
        If membershipService.ValidateUser(companyCodeToUse, model.CustCarrierFlag, model.UserName, model.Password, userInfo) Then
            FormsService.SignIn(model.UserName, model.RememberMe)
            Session("GMCUserInfo") = userInfo
            If Not String.IsNullOrEmpty(returnUrl) Then
                Return Redirect(returnUrl)
            Else
                Return RedirectToAction("Index", "Home")
            End If
        Else
            ModelState.AddModelError("", "The user name or password provided is incorrect.")
        End If
    End If
    ' If we got this far, something failed, redisplay form
    Return PartialView(model)
End Function

14 Answers, 1 is accepted

Sort by
0
Atanas Korchev
Telerik team
answered on 16 Feb 2011, 08:22 AM
Hi Donna Stewart,

 Unfortunately we cannot tell what causes the problem based on the pasted code. We need a runnable project in order to troubleshoot this case.

Regards,
Atanas Korchev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Donna Stewart
Top achievements
Rank 1
answered on 22 Feb 2011, 08:54 PM
I have opened a support ticket with a runnable project attached.  The ticket number is 396916.  Thank you so much for your help!

Donna
0
Thomas
Top achievements
Rank 1
answered on 05 Jul 2011, 07:41 PM
I don't know if this has been solved yet but this is what i did to fix the same type scenerio.

Use the telerik window to open a view with an iframe in it then in the iframe open the view that requires the postback in it.
0
Marc Gervais
Top achievements
Rank 1
answered on 06 Sep 2011, 04:20 PM
Is there a code sample that demonstrates this solution?
0
Thomas
Top achievements
Rank 1
answered on 06 Sep 2011, 04:40 PM
Create a new view using your AccountController and call it LoginPopUp.

In the view you just created add the below line of html to it.

<iframe src="/Account/LogOnWindow" frameborder="0" marginwidth="0" marginheight="0" height="400px" width="590px" scrolling="no" />

In your code stated above.  Change the "LoadContentFrom" to the below.

<div>
        <%  Html.Telerik().Window().Name("LogOnWindow") _
        .LoadContentFrom("LoginPopUp", "Account") _
        .Buttons(Function(buttons) buttons.Refresh().Maximize().Close()) _
        .Draggable(True) _
        .Height(575) _
        .Width(550) _
        .Resizable() _
        .Title("Log In") _
        .Visible(False) _
        .Render()
            %>
    </div>

You may need to add some javascript to finish the load event if the user properly authenticates to be able to close the popwindow and get back to the main window.  This could be accomplished by adding a ViewBag property to the LogOnWindow method and then validating it in the LogInWindow view.  If you do this you will need to set this property to false even if the user is not logged in, otherwise it will throw an exception.

@if(ViewBag.IsAutheticated)
{
<script type="text/javascript">
if(window.parent)
{
   window.parent.location = "some url or relative url you want the main page to go to";
}
</script>
}

Hope this helps.
0
Marc Gervais
Top achievements
Rank 1
answered on 06 Sep 2011, 07:15 PM
@Thomas:

Thanks for the quick response. I am havingin difficulty following along as I am not the one who posted the original question along with source. I am using Razor views instead of ASPX views and I'm thinking that may be what is causing some of my confusion.

Are you able to post a more concrete sample of how to get this working based upon the Telerik template project fr MVC3?

Thanks.
0
Donna Stewart
Top achievements
Rank 1
answered on 06 Sep 2011, 07:30 PM

I don't mean to confuse matters, but I am the original poster, so I thought I would show how I ended up doing this.  It is aspx not razor, so I'm not sure if it will help you... but here goes anyway...

Here is the source of the view from which the window pops up:

<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %>
<%-- The following line works around an ASP.NET compiler warning --%>
<%: ""%>
<script language="javascript" type="text/javascript">
         function logIn() {
            var window = $('#LogOnWindow').data('tWindow');
            window.ajaxRequest('<%= Url.Action("LogOn", "Account") %>');
            window.center().refresh();
            window.open();
        }
</script>
 
   <div style="float:right;">
    <%
        If Request.IsAuthenticated Then
    %>
            <%: Model.loggedInUserInfo._UserName%>
            [ <%: Html.ActionLink("Log Off", "LogOff", "Account")%> ]
    <%
    Else
    %>
            [ <a href="#" id="login" onclick="logIn()">Log In</a> ]
    <%       
    End If
    %>
        <%  Html.Telerik().Window().Name("LogOnWindow") _
        .Buttons(Function(buttons) buttons.Refresh().Maximize().Close()) _
        .Draggable(True) _
        .Height(575) _
        .Width(550) _
        .Resizable() _
        .Title("Log In") _
        .Visible(False) _
        .Render()
        %>
    </div>

Here is the source of the view which pops up - what you want to look at is the Html.BeginForm and the $('#logon-form').submit in the $(document).ready function - that is what submits the form and the window.location.replace loads the view you want if log in is successful.

<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of GMC_Hub_and_Spoke.LogOnModel)" %>
    <script type="text/javascript" language="javascript">
        $(document).ready(
            function () {
                $('input.focus').attr('value', ''); setTimeout(function () {
                    $(".focus").focus();
                }, 500);
 
                $('#logon-form').submit(function (e) {
                    var data = $(this).serialize();
                    $.post('<%= Url.Action("LogOn", "Account") %>', data, function (result) {
                        if (result.StatusCode != 1) {
                            $("#errorDiv").replaceWith('<div class="display-field" style="color:#FF3366; font-size:small;">' + result.MessageString + '</div>');
                        }
                        else {
                            $('#logon-form').closest('.t-window').data('tWindow').close();
                            window.location.replace('<%= Url.Action("Index", "Home") %>');
                        }
                    });
                    e.preventDefault();
                });
            }
        );
 
    </script>
    <% Using Html.BeginForm("LogOn", "Account", FormMethod.Post, New With {.id = "logon-form"})%>
    <div id="publicpage">
<%--           <p><img alt="GMC Logo" src="<%= Url.Content("~/Content/Images/GMC-Logo-100-x-76.jpg") %>" /><span class="publiccontentheader" style="padding-left:15px">GMC Log In</span></p>
--%>                <div id="loginmain">
                    <p class="homecontentheader">Log In</p>
<%--                    <div id="customerField"><p>
                            <%: Html.LabelFor(Function(m) m.CompanyCode)%> 
                            <%: Html.TextBoxFor(Function(m) m.CompanyCode, New With {.class = "focus"})%>
                            <%: Html.ValidationMessageFor(Function(m) m.CompanyCode)%>
                            </p>
                    </div>
--%>                    <p>
                        <%: Html.LabelFor(Function(m) m.UserName) %> 
                        <%: Html.TextBoxFor(Function(m) m.UserName, New With {.class = "focus"}) %>
                        <%: Html.ValidationMessageFor(Function(m) m.UserName) %>
                    </p>
                    <p>
                        <%: Html.LabelFor(Function(m) m.Password) %>
                        <%: Html.PasswordFor(Function(m) m.Password) %>
                        <%: Html.ValidationMessageFor(Function(m) m.Password) %>
                    </p>
                    <p>
                        <%: Html.CheckBoxFor(Function(m) m.RememberMe) %>
                        <%: Html.LabelFor(Function(m) m.RememberMe) %>
                    </p>
                    <p>
                        <input type="submit" value="Log On" />
                        <%: Html.ValidationSummary(True, "Login was unsuccessful. Please correct the errors and try again.")%>
                    </p>
                    <div id = "errorDiv"></div>
               </div>
        </div>
    <% End Using %>

Here's the controller code :

<HttpPost()> _
Public Function LogOn(ByVal form As FormCollection) As JsonResult
    Dim statusReturn As New com.gmcps.StatusReturn
    If ModelState.IsValid Then
        Dim userInfo As New LoginResultVO
        Dim membershipService As New GMCMembershipProvider
        Dim rememberMe As String = form.Get("RememberMe")
 
        If membershipService.ValidateUser("1", False, form.Get("UserName"), form.Get("Password"), userInfo) Then
            FormsService.SignIn(form.Get("UserName"), form.Get("RememberMe"))
 
            Session("GMCUserInfo") = userInfo
            Session("loadFirstTab") = "true"
            statusReturn.StatusCode = userInfo._Status
            statusReturn.MessageString = userInfo._StatusMessage
            Return Json(statusReturn)
        Else
            statusReturn.StatusCode = userInfo._Status
            statusReturn.MessageString = userInfo._StatusMessage
            ModelState.AddModelError("", "The user name or password provided is incorrect.")
        End If
    End If
 
    ' If we got this far, something failed, redisplay form
    Return Json(statusReturn)
End Function

Hope this helps,
Donna

0
Thomas
Top achievements
Rank 1
answered on 06 Sep 2011, 08:12 PM
The solution below is for Razor MVC 3.

I will try to explain as best i can.  I am assuming that you are using a version of Microsoft Visual Studio and you already have the Telerik component displaying on the page and it is navigating to a full page view on post when you want it to return to the popup window.

1. Navigate to Views\Shared and right click on the Shared folder and select Add then New Item.  In the window that comes up select "MVC 3 Layout Page (Razor)" and name it _LayoutEmpty.cshtml.

2. Open the AccountController.cs file or whichever controller you are using and add the below method.

public ActionResult LoginPopup()
        {
            return View();
        }


3. Right click the word "LoginPopup" in the method that you just posted and select "Add View".  Now where it says "Use a layout or master page, you will want to select "_LayoutEmpty". and the click "Add".

If the page doesn't open after you have clicked "Add" it will be located at Views\Account\LoginPopup.cshtml.  Open this file.

Insert the iframe below into the html of the LoginPopup.cshtml view.  This iframe will point at the view that you really want to display to the user.  This could be your login, registration, payment, or really anything.  Change the width and the height of the iframe to suit your needs.

<iframe src="/Account/LogOnWindow" frameborder="0" marginwidth="0" marginheight="0" height="400px" width="590px" scrolling="no" />


4. In the view that has the action that will open the Telerik window set the property of LoadContentFrom to...

.LoadContentFrom("LoginPopUp", "Account")


This works because the post event is contained within the iframe, which also creates a problem for redirecting the main page that opened the popwindow in the first place after the user has logged in.  To resolve this you will need to add javascript to reference the parent of the iframe.  Not really knowing what your code looks like kind of makes it hard to explain how to resolve this. 

Now i am assuming that you have some sort of Model being passed to the view.  Alternatively you can use the ViewBag or Context.User.identity.IsAuthenticated (only if you are setting the value of this) in place of "Model.IsAuthenticated".

1.  Add a property of type bool to the model called "IsAuthenticated" set the default value to false.
2.  In the "LoginWindow.cshtml" add the following code. (This is the view that is loading in the iframe not the one i had you create.)
@if(Model.IsAutheticated)
{
<script type="text/javascript">
if(window.parent)
{
   window.parent.location = "some url or relative url you want the main page to go to";
}
</script>
}

3.  When the user is Authenticated set the value of "IsAuthenticated" to true.  The script will run and the  user will be redirected.

Alternatively, you could use jquery to interupt the post event and then use jquery ajax to return the model and return a json response and skip the iframe all together, but that is much more complicated to do.

0
Marc Gervais
Top achievements
Rank 1
answered on 07 Sep 2011, 04:58 PM
@Donna:

Thanks for your reply. I have managed to get everything working (using your solution) except for the closing of the popup window following a successful login. The line that seemed to be failing was:
$('#login-form').closest('.t-window').data('tWindow').close();

So I simply commented it out and carried on and because the page is being refreshed/reloaded, the login Window disappears due to an authenticated User.

However, I'd still like to understand why this may have failed in case I wish to make use of this solution on other pages where closing the Window will be important. Do you have any ideas?

Thanks.
0
Donna Stewart
Top achievements
Rank 1
answered on 07 Sep 2011, 06:57 PM
Hi Marc,

I am so glad you have things working (pretty much).  I can't take credit for the solution.  I had much help from the Telerik team.  As far as why the closing of the window would fail, I really do not know, unless 'login-form' is not the id you used for your from in the BeginForm statement. 
<% Using Html.BeginForm("LogOn", "Account", FormMethod.Post, New With {.id = "logon-form"})%>

Were you getting a javascript error? What error were you getting?  Maybe someone smarter than me can help out.

Thanks,
Donna
0
Marc Gervais
Top achievements
Rank 1
answered on 07 Sep 2011, 07:55 PM
Hi Donna:

Making sure the ids all matched was the first thing I tried...in fact, they were not correct the first time I ran the application.

I do not get a javascript error unless I place the code in a try/catch...at that point I get : Unable to get value of the property 'close': object is null or undefined.

Oh well...I'm going to carry on with my project and perhaps someone may see this and offer some tidbit of assistance.

Thanks for your help. I really appreciate it.

Marc.
0
Donna Stewart
Top achievements
Rank 1
answered on 07 Sep 2011, 08:09 PM
Well, I figured you had tried that since it is pretty obvious.  The only other thing I can think of, which is pretty obvious as well, but has bitten me before, is have you included the telerik.window.min.js in your ScriptRegistrar?
.DefaultGroup(Function(addGroup) addGroup.Add("telerik.window.min.js")) _

I'm glad I could help!  Good luck with everything!

Donna
0
Marc Gervais
Top achievements
Rank 1
answered on 07 Sep 2011, 11:35 PM
I had a look and have not found where I am referencing that script file. However, I have gone through the Telerik example project and cannot find it there either. In which file have you placed this reference?

Thanks.
0
Sai
Top achievements
Rank 1
answered on 25 Nov 2011, 07:31 AM
Hey Marc,
                Can you send me the sample code for in razor. I need exactly the same login functionality what donna mentioned. But I had hard time in understanding ASPX and VB.  It would be helpful if you can explain me what partial classes, models, controllers and regular classes need to be used or send your sample code to sai530@ymail.com if you can.  I'm newbie to MVC

Thanks in advance
Sai
Tags
Window
Asked by
Donna Stewart
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
Donna Stewart
Top achievements
Rank 1
Thomas
Top achievements
Rank 1
Marc Gervais
Top achievements
Rank 1
Sai
Top achievements
Rank 1
Share this question
or