2 Stimmen

ASP C# Wie man sauberen GUI-Code programmiert

Seit ein paar Monaten programmiere ich ASP C#. Ich programmiere immer viel Code in den Events und im Load Event prüfe ich den Querystring auf gültige Daten. Dies ist einige Beispiel-Code habe ich in einem meiner Projekte:

protected void Page_Load(object sender, EventArgs e)
{
    if (Controller.Manual == null)
    {
        Response.Redirect("login.aspx");
    }

    lblLocation.Text = "<a href='viewdocument.aspx'>" + Controller.Manual.Title + "</a>";

    if (Request.QueryString["gchap"] != null)
    {
        if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
        {
            genchap = Convert.ToInt32(Request.QueryString["gchap"]);

            FillGeneralList();

            SetChapterTitle();
        }
    }
    if (Request.QueryString["qchap"] != null)
    {
        if (Controller.IsNumeric(Request.QueryString["qchap"].ToString()))
        {
            qualchap = Convert.ToInt32(Request.QueryString["qchap"]);

            FillQualityList();

            SetChapterTitle();
        }
    }

    // Check document Id is set (did)
    if (Request.QueryString["did"] != null)
    {
        if (Controller.IsNumeric(Request.QueryString["did"].ToString()))
        {
            docId = Convert.ToInt32(Request.QueryString["did"]);

            DetermineView();
        }
    }

}

Ich weiß, dass es einen Weg geben muss, dies auf eine saubere Art und Weise zu erreichen. Und das ist nur das Ladeereignis. Auf andere Ereignisse, wie Klick und onchange Ereignisse habe ich ähnlichen Code. Ich denke, das ist Spaghetti-Code und nicht gut geordnet. Können Sie mir also sagen, wie ich meinen Code ordnen kann?

EDITAR:

Was ich wissen möchte, ist, gibt es eine ordentlichere Art und Weise zu, sagen wir, eine Listbox zu füllen? Und wo prüfe ich, ob ein Querystring-Wert gültige Daten enthält? Wo prüfe ich, ob die Daten (Eingabe/Querystring) eine Zahl sind? Und wo sollte man den Code zur Validierung des Querystrings unterbringen? Auch im load event?

4voto

mmcdole Punkte 88559

Ich fühle Ihren Schmerz mit einigen der Organisationsprobleme mit ASP.NET-Websites. Ich habe ähnlichen Code zu Ihrem auf mehrere Projekte hatte.

Wenn Sie die Wahl zwischen verschiedenen Frameworks haben, könnten Sie ASP.NET MVC in Betracht ziehen. Dies ermöglicht Ihnen eine klare Trennung zwischen der Ansicht (HTML), den Controllern (alle Aktionen und Geschäftslogik) und dem Modell (Datenbank). Auf diese Weise haben Sie null Code in Ihren Codebehind-Dateien, es bleibt alles schön und ordentlich in Controllern.

3voto

Ian G Punkte 28438

Versuchen Sie es mit TryParse ( zum Beispiel ) und Sie können den gesamten Code, der wie folgt aussieht, vereinfachen

xx.IsNumeric(Request.QueryString["qchap"].ToString())

y

Convert.ToInt32(Request.QueryString["gchap"]);

und die Anzahl der Anrufe bei Request.QueryString Variablen

Sie könnten etwas versuchen wie

Ursprünglicher Code

if (Request.QueryString["gchap"] != null)
{
    if (Controller.IsNumeric(Request.QueryString["gchap"].ToString()))
    {
        gchap = Convert.ToInt32(Request.QueryString["gchap"]);

        FillGeneralList();

        SetChapterTitle();
    }
}

Anregung

int? gchap; //nullable types thanks Richard :D
if (!int.TryParse(Request.QueryString["gchap"], out id)) {gchap = null};

if (gchap != null) {
     FillGeneralList();
     SetChapterTitle();
}
// you could make this neater with your own little method

Schauen Sie sich diesen Beitrag an Wie testen Sie Ihre Request.QueryString[]-Variablen?

2voto

RuudKok Punkte 5222

Versuchen Sie, den sich wiederholenden Code in einer separaten Funktion zu erfassen. (qchap / gchap)

z.B.:

qualchap = ConvertFillAndSet(Request.Querystring["qchap"]);
genchap = ConvertFillAndSet(Request.QueryString["gchap"]);

private int ConvertFillAndSet(string qrystring)
{
  int numberToReturn = 0;      

  //if the conversion was ok -> true, else false
  if (Int32.TryParse(qrystring,numberToReturn))
  {
    FillQualityList();
    SetChapterTitle();
  }

  //returns 0 if tryparse didn't work
  return numberToReturn;
}

2voto

Robert Paulson Punkte 16995

Wo soll man anfangen? Leider trotz anderer Kommentare, Sie sind nicht wirklich etwas schreiben, die "Web-Formen" spezifisch ist. So bewegen, um MVC wird nicht auf magische Weise machen Ihren Code besser.


1 Führen Sie Ihre eigene Authentifizierung nicht durch: Verwenden Sie Formular-Authentifizierung es sei denn, Sie haben einen zwingenden Grund, dies nicht zu tun. Wenn Sie die Formularauthentifizierung verwenden, müssen Sie nicht auf jeder Seite Code schreiben, um zu prüfen, ob Sie angemeldet sind. Das Framework übernimmt das für Sie.


2 Lernen Sie zur Nutzung der Server-Kontrollen :

Auch wie andere schreiben, sollten Sie nicht HTML in Code schreiben, besonders nicht für etwas so Triviales. Webformulare zwingen Sie auch nicht dazu.

  <!-- this is in MyPage.aspx -->
  <asp:HyperLink id="viewLink" runat="server" />

  // in the code-behind file MyPage.aspx.cs
  viewLink.NavigateUrl = "~/viewdocument.aspx";
  viewLink.Text = Controller.Title;

Wenn Sie bei Webformularen bleiben wollen, müssen Sie sich mit der ASP.Net Seite Lebenszyklus


3 Ihr Code muss überarbeitet werden. Ganz gleich, ob es sich um Webformulare, PHP oder MVC handelt. Hier sind einige grundlegende Refactorings, und nichts davon ist wirklich .net-spezifisch. Ich werde sie in kleinen Schritten durchgehen.

// this may be a good candidate for an extension method
int? ConvertNullable(string nullableInt) {
  if( string.IsNullOrEmpty(nullableInt) )
    return null;

  int value;
  if( Int32.TryParse(nullableInt, out value) )
    return value;

  return null;
}

was Ihnen dann erlaubt zu schreiben.

int genchap? = ConvertNullable(Request.QueryString["gchap"]);
int qualchap? = ConvertNullable(Request.QueryString["qualchap"]);
int docId? = ConvertNullable(Request.QueryString["did"]);

FillQualityList(genchap,qualchap);
SetChapterTitle(genchap,qualchap);
DetermineView(docId);

aber die Weitergabe vieler Primitive ist mühsam und fehleranfällig, so dass wir manchmal eine kleine Klasse erstellen, um die Daten zu kapseln, in diesem Fall die Seiteninitialisierungsinformationen.

class ChapterView
{
  public int? GenChapter {get; set;}
  public int? QualChapter {get; set;}
  public int? DocumentId {get; set;}
}

private ChapterView GetChapterView()
{
  return new ChapterView
  {
    GenChapter = ConvertNullable(Request.QueryString["gchap"]),
    QualChapter = ConvertNullable(Request.QueryString["qualchap"]),
    DocumentId = ConvertNullable(Request.QueryString["did"])
  }
}

Ich habe keine Ahnung, was GenChap und QualChap sind, aber sie sind etwas knapp, und man könnte das Refactoring abschließen, um sie im Code besser lesbar zu machen. Aber auch ohne bessere Namen haben wir jetzt einen besser lesbaren Code.

ChapterView chapterView = GetChapterView();

FillQualityList(chapterView);
SetChapterTitle(chapterView);
DetermineView(chapterView);

Und schließlich können Sie feststellen, dass Sie nicht wirklich brauchen, um diese jedes Mal, wenn die Seite ausgeführt wird, um aus der Abfragezeichenfolge zu lesen aufrufen. Wenn Sie sich über die Asp.Net Page LifeCycle Sie wissen, dass sich die Ereignisse ändern können GenChapter oder etwas anderes, das sich auf die Darstellung der Seite auswirkt. Möglicherweise ist es besser, die Ansicht im PreRender einzurichten, anstatt FillQualityList immer wieder aufzurufen.

ChapterView chapterView;

Page_Load()
{
  if( !IsPostback )
  {
    ChapterView chapterView = GetChapterView();
  }
  else
  {
    chapterView = (ChapterView) ViewState["chapterview"];
  }
}

NextChapter_Click()
{
  chaperView.NextChapter();
}

Page_PreRender()
{
  FillQualityList(chapterView);
  SetChapterTitle(chapterView);
  DetermineView(chapterView);}

  // make sure class is marked [Serializable]
  ViewState["chapterview"] = chapterView; 
}

1voto

Raj Punkte 6790

Sie sollten einen mehrschichtigen Ansatz verfolgen, d. h.: den gesamten Datenzugriffscode in die Datenzugriffsschicht, die gesamte Geschäftslogik (einschließlich der Validierungen) in die Geschäftsschicht und den gesamten Modellcode in die Geschäftsobjektschicht einfügen.

und schließlich für ui - versuchen Sie, nie generieren html mark up aus dem Code so weit wie möglich. auch immer eine Root-Klasse für Ihre Aspx-Seiten, wo es gemeinsame Methoden bereits implementiert hat. dann subclass diese Root-Klasse für jede andere Aspx-Seiten

wenn Sie HTML-Markup in Ihrem c#-Code fest einbinden wollen, kann ich Ihnen versichern, dass dies immer zu einem großen Chaos führen würde (basierend auf meiner eigenen Erfahrung)

aber es gibt Situationen, in denen Sie einfach nicht vermeiden können. für solche Fälle - das ist, was ich tue - ich loswerden der Code hinter und einfach setzen, dass Code in meinem Aspx / Ascx-Datei selbst. auf diese Weise, wenn ich meine ui basierend auf nie endenden Client-Anfragen ändern müssen, ich nicht haben, um meinen Code neu zu kompilieren - ich ersetzen Sie einfach meine Aspx / Ascx-Dateien auf dem Staging / Produktionsserver.

Sie wissen ja, wie Kunden sind: hmmm, können Sie den schwarzen Streifen ein wenig grau aussehen lassen, können Sie den Abstand zwischen den Zeilen vergrößern, können Sie den Text dieses Hyperlinks ändern... Anfragen wie diese scheinen nie zu enden :-)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X