2012-01-09 3 views
3

Я пытаюсь подражать виджетам iGoogle для внутреннего веб-сайта моей компании, и у меня возникает проблема, когда я отправляю сообщение. Ошибка, которую я получаю, -Что лучше всего загружать виджеты асинхронно?

Sys.WebForms.PageRequestManagerServerErrorException: Sys.WebForms.PageRequestManagerServerErrorException: информация о состоянии недопустима для этой страницы и может быть повреждена.

Эта ошибка возникает при нажатии кнопки LayoutButton1. Странно, что эта ошибка возникает в IE 9 и Chrome 16, но не в Firefox 9.

Как я могу загрузить страницы ASPX или пользовательские элементы управления, используя мой подход? Я что-то упускаю? Есть ли лучший способ сделать это?

Вот желаемое поведение я хочу иметь:

1) Пользователь попадает на страницу с первого раза и на странице полностью загружает. Каждый виджет отображает gj-загрузчик ajax. 2) После полной загрузки страницы я делаю асинхронные вызовы для каждого виджета для загрузки их содержимого. Содержимое каждого виджета содержит элементы управления ASP.NET, такие как элементы управления сеткой и элементы управления деревом, поэтому содержимое виджета должно быть пользовательским элементом управления или страницей ASPX. В моем доказательстве концептуального проекта я использую ASPX-страницы. 3) После того, как содержимое виджета будет восстановлено, gif-загрузчик ajax заменяется разметкой, полученной мной от асинхронного вызова.

Вот код, который я использую. Обратите внимание, что я использую серверные элементы Telerik ASP.NET для виджетов (которые не должны влиять на мою проблему).

<script type="text/javascript"> 
    $(document).ready(function() 
    { 
     // Wires a client-side click event to the layout buttons. 
     $('.layouts').find('input').live('click', function() 
     { 
      if ($(this).attr('class') == 'layoutSelected') 
      { 
       return false; 
      } 
      else 
      { 
       return true; 
      } 
     }); 
    }); 

    // Load content of all widgets. 
    function loadAllWidgets() 
    { 
     loadWidget1(); 
    } 

    // Loads widget #1. 
    function loadWidget1() 
    { 
     $(document).ready(function() 
     { 
      PageMethods.LoadWidgetContent1(onWidgetContentLoadSucceeded, onWidgetContentLoadFailed); 
     }); 
    } 

    // Widget content load success. 
    function onWidgetContentLoadSucceeded(result, userContext, methodName) 
    { 
     switch (methodName) 
     { 
      case "LoadWidgetContent1": 
       $('#Widget1').find('.widgetContent').html(result); 
       break; 
     } 
    } 

    // Widget content load fail. 
    function onWidgetContentLoadFailed(error, userContext, methodName) 
    { 
     alert(error); 
    } 
</script> 

<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" runat="server" /> 
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
    <ContentTemplate> 
     <div style="padding-bottom: 10px;"> 
      <table class="layouts"> 
       <tr> 
        <td>Layout:</td> 
        <td><asp:Button ID="LayoutButton1" CommandArgument="1" OnClick="LayoutButton_Click" runat="server" /></td> 
       </tr> 
      </table> 
     </div> 
     <div> 
      <telerik:RadDockLayout ID="RadDockLayout1" runat="server"> 
       <telerik:RadDockZone ID="RadDockZone1" CssClass="dockZone dockZoneWide" runat="server" /> 
      </telerik:RadDockLayout> 
     </div> 
    </ContentTemplate> 
</asp:UpdatePanel> 

protected void LayoutButton_Click(object sender, EventArgs e) 
{ 
    var layoutNumber = Convert.ToInt32(((Button)sender).CommandArgument); 

    switch (layoutNumber) 
    { 
     case 1: 
      LayoutButton1.CssClass = "layoutSelected"; 
      LayoutButton2.CssClass = string.Empty; 
      LayoutButton3.CssClass = string.Empty; 
      LayoutButton4.CssClass = string.Empty; 

      RadDockZone1.CssClass = "dockZone dockZoneWide"; 
      RadDockZone2.CssClass = "dockZone dockZoneNormal"; 
      RadDockZone3.CssClass = "dockZone dockZoneNormal"; 
      RadDockZone4.CssClass = "dockZone dockZoneNormal"; 
      RadDockZone5.CssClass = "dockZone dockZoneNormal"; 

      RadDockZone4.Visible = true; 
      RadDockZone5.Visible = false; 
      CreateWidgets(); 

      break; 
    } 
} 

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!IsPostBack) 
    { 
     CreateWidgets(); 
    } 
} 

private void CreateWidgets() 
{ 

    var radDock = new RadDock 
    { 
     Closed = false, 
     DefaultCommands = DefaultCommands.All, 
     ID = "Widget 1", 
     Resizable = false, 
     Skin = "Sitefinity", 
     Title = "Widget 1", 
    }; 

    var divTag = new HtmlGenericControl("div"); 
    divTag.Attributes.Add("class", "widgetContent"); 

    var image = new Image 
    { 
     CssClass = "ajaxLoader", 
     ImageUrl = "~/images/transparent.gif", 
     ToolTip = "loading..." 
    }; 

    divTag.Controls.Add(image); 
    radDock.ContentContainer.Controls.Add(divTag); 
    RadDockLayout1.Controls.Add(radDock); 
    radDock.Dock(RadDockZone1); 


    ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "LoadAllWidgets", "loadAllWidgets();", true); 
} 

[WebMethod] 
public static string LoadWidgetContent1() 
{ 
    var stringWriter = new StringWriter(); 
    HttpContext.Current.Server.Execute("~/WidgetContent/WidgetContent1.aspx", stringWriter); 
    return stringWriter.ToString(); 
} 
+0

Обновление не может обрабатывать более одного обновления одновременно, и вы, вероятно, сделаете это, вы обновите панель до завершения предыдущего обновления, а состояние представления будет повреждено - также панель обновления имеет свои выигранные функции, но вы используете готовый jQuery, это также создает проблемы. – Aristos

+0

Я удалил панель обновления, и ошибка, которую я получаю, - «Информация состояния недействительна для этой страницы и может быть повреждена». – Halcyon

ответ

1

ОК - после нескольких часов и нескольких подходов к этому, я думаю, что нашел хорошее решение. Решение, которое я нашел работать, заключается в использовании пользовательских элементов управления вместо ASPX-страниц. Это позволит использовать теги сервера и предотвращает возникновение недопустимого состояния представления. Единственное изменение, которое мне нужно было сделать в коде-позади было обновить веб-метод как так:

[WebMethod] 
public static string LoadWidgetContent() 
{ 
    Page pageHolder = new Page(); 
    UserControl viewControl = (UserControl)pageHolder.LoadControl("~/WidgetContent/WidgetContent.ascx"); 
    pageHolder.Controls.Add(viewControl); 

    StringWriter output = new StringWriter(); 
    HttpContext.Current.Server.Execute(pageHolder, output, false); 

    return output.ToString(); 
} 

Этот подход позволил мне продолжать использовать панель обновления и загрузить виджеты раз страница была полностью загружена. I ended up using Scott Gu's blog as a reference. Это немного устарело, но основной принцип использования веб-методов по-прежнему сохраняется.

0

Подход, который вы используете, является правильным и может работать. Если вам нужен пример профессиональных виджетах - взгляните на Telerik Sitefinity. Продукт является коммерческим, но вы можете скачать пробную версию и протестировать ее.

Смежные вопросы