2009-06-10 3 views
15

Kann mir jemand erklären, warum Server.Execute() meine gerenderten UserControls benötigt, um <form> Tags zu enthalten (oder alternativ, was ich falsch mache, was Server macht. Execute() erfordern Formular-Tags in meinen UserControls)?Probleme beim Rendern von UserControl mit Server.Execute() in einem ASMX-Webdienst

Ich habe eine ASMX Dienst erstellt dynamisch Benutzersteuerelemente über JQuery + JSON geladen werden, wie folgt:

ControlService.asmx

<%@ WebService Language="C#" CodeBehind="ControlService.asmx.cs" Class="ManagementConcepts.WebServices.ControlService" %> 

ControlService.cs

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.Web.Script.Services.ScriptService] 
public class ControlService : System.Web.Services.WebService 
{ 
    private string GetControl(String controlName, String ClassId) 
    { 
     Page page = new Page(); 
     UserControl ctl = (UserControl)page.LoadControl(controlName); 

     page.Controls.Add(ctl); 
     StringWriter writer = new StringWriter(); 
     HttpContext.Current.Server.Execute(page, writer, false); 
     return writer.ToString(); 
    } 
    [WebMethod] 
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
    public string GetSimpleControl(string ClassId) 
    { 
     return GetControl("SimpleControl.ascx", ClassId); 
    } 
} 

I die Steuerung laden eine Seite über das folgende Bit von JQuery, das ein mit dem ID ContentPlaceholder mit dem HTML ersetzt, das von dem Dienst zurückgegeben wird:

JQueryControlLoadExample.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JQueryControlLoadExample.aspx.cs" Inherits="ControlService_Prototype._Default" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server"> 
    <title>ControlService Prototype</title> 
</head> 
<body> 
    <form id="theForm" runat="server" action="JQueryControlLoadExample.aspx"> 
     <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" > 
      <Scripts> 
       <asp:ScriptReference NotifyScriptLoaded="true" Path="~/Scripts/jquery-1.3.2.js" /> 
      </Scripts> 
     </asp:ScriptManager> 
     <div> 
     <asp:HiddenField runat="server" ID="hdncourse"/> 
     <asp:HiddenField runat="server" ID="hdnTargetContent" Value="GetSimpleControl"/> 
     <div runat="server" id="ContentPlaceholder" class="loading"></div> 
     </div> 
     <script type="text/javascript"> 
      $(document).ready(function() { 
       var servicemethod = document.getElementById("hdnTargetContent").value; 
       $.ajax({ 
       type: "POST", 
        url: "ControlService.asmx/" + servicemethod, 
        data: "{'ClassId':'"+document.getElementById("hdncourse").value+"'}", 
        contentType: "application/json; charset=utf-8", 
        dataType: "json", 
        success: function(msg) { 
         $('#ContentPlaceholder').html(msg.d); 
        } 
       }); 
      }); 
     </script> 
    </form> 
</body> 
</html> 

Das funktioniert mit einem großen Nachteil. Wenn ich nicht eine Form innerhalb der ASCX Kontrolle Markup definieren dann HttpContext.Current.Server.Execute() löst eine Httpexception mit der folgenden Meldung:

Control 'hdnspecialoffer' of type 'HiddenField' must be placed inside a form tag with runat=server.

SimpleControl.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SimpleControl.ascx.cs" Inherits="ControlService_Prototype.UserControls.SimpleControl" %> 
    <asp:HiddenField runat="server" ID="hdnspecialoffer"/> 

Wenn ich dem ascx-Steuerelement ein form-Tag hinzufügte, um dieses Problem zu umgehen, würde das Formular gerendert, aber der Renderer schreibt das form-Tag im Steuerelement neu, so dass es an den ASMX-Dienst zurückgesendet wird und nicht auf der ASPX-Seite.

Ich googelte herum und entdeckte Scott Guthries exzellentes ViewManager Beispiel. Ich sehe nichts grundsätzlich anders als das, was er dort getan hat, was mich zu der Überzeugung bringt, dass das, was ich tue, funktionieren sollte.

Antwort

21

Sieht aus wie die Antwort in den Kommentaren für die ViewManager

begraben wurde eine Klasse wollen werden, die von Seite und überschreibt den Scheck für Server erbt in einem Formular-Steuerelemente nicht

public class FormlessPage : Page 
{ 
    public override void VerifyRenderingInServerForm(Control control) 
    { 
    } 
} 

Dann, wenn Sie machen die Kontrolle, verwenden

Page page = new FormlessPage(); 
UserControl ctl = (UserControl)page.LoadControl(controlName); 
//etc 

ich gehe davon aus Sie die Möglichkeit, Ereignisse von Kontrollen auf diese Weise gemacht Brennen haben zu verlieren.

+0

Ich neige dazu, diese Antwort zu akzeptieren, wie es wahr klingt, aber ich möchte es zuerst ausprobieren (was nicht für ein paar Tage sein wird). –

0

Sie könnten Ihre GetControl() Methode wie folgt ändern:

private string GetControl(String controlName, String ClassId) 
{ 
    Page page = new Page(); 
    StringWriter writer = new StringWriter(); 
    page.Server.Execute(controlName, writer, false); 
    return writer.ToString(); 
} 
+0

System.Web.UI.Page nicht() Execute-Methoden hat, soweit ich das beurteilen kann. Meinst du 'page.Server.Execute (controlName, writer, false)'? –

+0

Entschuldigung. Das ist es was ich meinte. – ichiban

+0

Leider funktioniert das nicht für UserControls (ASCX). page.Server.Execute() funktioniert nur für ASPX-Seiten. –

1

Anstatt eine asp.net versteckte Kontrolle auf Ihrer Benutzersteuerung zu verwenden, benutzen Sie einfach einen regelmäßigen html versteckten Eingang mit den Code-Tags <%%> zu Füllen Sie die Daten wie folgt aus:

<input id="Hidden1" type="hidden" value="<%= text %>"/> 

"Text" ist eine öffentliche Variable im Code hinter der Datei.

Dies funktionierte für mich und brauchte kein Formular mit runat="server".

+0

Ihre Idee wird in diesem Fall nicht funktionieren. Mein Beispiel ruft den Web-Service vom Browser auf und ersetzt das versteckte Feld durch den zurückgegebenen Inhalt in Javascript auf dem Client. <% %> wird auf dem Server verarbeitet. –

0
<System.Web.Services.WebMethod()> _ 
Public Shared Function GetDetails(ByVal filename As String) As String 
    Dim page As Page = New Page() 
    Dim ctl As recDetails = CType(page.LoadControl("~/Controles/recDetails.ascx"), recDetails) 
    ctl.FileName = filename 

    page.EnableEventValidation = False 
    Dim _form As New HtmlForm() 
    page.Controls.Add(_form) 
    _form.Controls.Add(ctl) 

    Dim writer As New System.IO.StringWriter() 
    HttpContext.Current.Server.Execute(page, writer, False) 
    Dim output As String = writer.ToString() 
    writer.Close() 
    Return output 
End Function 

Sie das Formular hinzufügen dinamically

0
<System.Web.Services.WebMethod()> _ 
Public Shared Function GetDetails(ByVal filename As String) As String 
    Dim page As Page = New Page() 
    Dim ctl As recDetails = CType(page.LoadControl("~/Controles/recDetails.ascx"), recDetails) 
    ctl.FileName = filename 

    page.EnableEventValidation = False 
    Dim _form As New HtmlForm() 
    page.Controls.Add(_form) 
    _form.Controls.Add(ctl) 

    Dim writer As New System.IO.StringWriter() 
    HttpContext.Current.Server.Execute(page, writer, False) 
    Dim output As String = writer.ToString() 
    writer.Close() 
    Return output 
End Function 

Sie das Formular hinzufügen dinamically