ASP.NET Web Sayfalarına Giriş - Veritabanı Verilerini Güncelleştirme

yazan: Tom FitzMacken

Bu öğreticide, ASP.NET Web Sayfaları (Razor) kullanırken var olan bir veritabanı girişini güncelleştirme (değiştirme) gösterilmektedir. ASP.NET Web Sayfalarını Kullanarak Formları Kullanarak Veri Girme yoluyla seriyi tamamladığınız varsayılır.

Öğrenecekleriniz:

  • Yardımcıdaki WebGrid tek bir kaydı seçme.
  • Veritabanından tek bir kaydı okuma.
  • Veritabanı kaydındaki değerlerle formu önceden yükleme.
  • Veritabanında var olan bir kaydı güncelleştirme.
  • Bilgileri görüntülemeden sayfada depolama.
  • Bilgileri depolamak için gizli alan kullanma.

Ele alınan özellikler/teknolojiler:

  • Yardımcı WebGrid .
  • SQL Update komutu.
  • Database.Execute yöntemi.
  • Gizli alanlar (<input type="hidden">).

Oluşturacakların

Önceki öğreticide veritabanına kayıt eklemeyi öğrendin. Burada, düzenleme için bir kaydı görüntülemeyi öğreneceksiniz. Filmler sayfasında, yardımcıyı WebGrid her filmin yanında bir Düzenle bağlantısı görüntüleyebilecek şekilde güncelleştireceksiniz:

Her film için bir 'Düzenle' bağlantısı içeren WebGrid ekranı

Düzenle bağlantısına tıkladığınızda, sizi film bilgilerinin zaten formda olduğu farklı bir sayfaya götürür:

Düzenlenecek filmi gösteren Filmi Düzenle sayfası

Değerlerden herhangi birini değiştirebilirsiniz. Değişiklikleri gönderdiğinizde, sayfadaki kod veritabanını güncelleştirir ve sizi film listesine geri götürür.

İşlemin bu bölümü, önceki öğreticide oluşturduğunuz AddMovie.cshtml sayfası gibi çalışır, bu nedenle bu öğreticinin çoğu tanıdık olacaktır.

Tek bir filmi düzenlemenin birkaç yolu vardır. Uygulanması ve anlaşılması kolay olduğundan gösterilen yaklaşım seçildi.

Başlamak için Filmler sayfasını güncelleştirerek her film listesinin bir Düzenle bağlantısı da içermesini sağlayın.

Movies.cshtml dosyasını açın.

Sayfanın gövdesinde bir sütun ekleyerek işaretlemeyi WebGrid değiştirin. Değiştirilen işaretleme şu şekildedir:

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
        grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
        grid.Column("Title"),
        grid.Column("Genre"),
        grid.Column("Year")
    )
)

Yeni sütun şu sütundur:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID)">Edit</a>)

Bu sütunun amacı, metninde "Düzenle" yazan bir bağlantı (<a> öğe) göstermektir. Peşinde olduğumuz şey, sayfa çalıştığında aşağıdakine benzeyen ve her film için farklı bir değere id sahip bir bağlantı oluşturmaktır:

http://localhost:43097/EditMovie?id=7

Bu bağlantı EditMovie adlı bir sayfayı çağırır ve sorgu dizesini ?id=7 bu sayfaya geçirir.

Yeni sütunun söz dizimi biraz karmaşık görünebilir, ancak bunun nedeni birkaç öğeyi bir araya getiriyor olmasıdır. Her bir öğe basittir. Yalnızca öğeye konsantre olursanız şu işaretlemeyi <a> görürsünüz:

<a href="~/EditMovie?id=@item.ID)">Edit</a>

Kılavuzun nasıl çalıştığıyla ilgili bazı arka plan: kılavuz her veritabanı kaydı için bir satır ve veritabanı kaydındaki her alanın sütunlarını görüntüler. Her kılavuz satırı oluşturulurken, item nesne bu satır için veritabanı kaydını (öğe) içerir. Bu düzenleme, kodda söz konusu satıra ilişkin verilere ulaşmak için bir yol sağlar. Burada gördüğünüz şey budur: ifade item.ID geçerli veritabanı öğesinin kimlik değerini alıyor. , item.Genreveya item.Yearkullanarak item.Titleveritabanı değerlerinden herhangi birini (başlık, tür veya yıl) aynı şekilde alabilirsiniz.

İfade "~/EditMovie?id=@item.ID , hedef URL'nin (~/EditMovie?id=) sabit kodlanmış bölümünü dinamik olarak türetilmiş bu kimlikle birleştirir. (Önceki öğreticide işlecini gördünüz ~ ; geçerli web sitesi kökünü temsil eden bir ASP.NET işlecidir.)

Sonuç olarak, sütundaki işaretlemenin bu bölümü yalnızca çalışma zamanında aşağıdaki işaretlemeye benzer bir şey üretir:

href="/EditMovie?id=2"

Doğal olarak, gerçek değeri id her satır için farklı olacaktır.

Kılavuz Sütunu için Özel Görüntü Oluşturma

Şimdi kılavuz sütununa geri dönün. Başlangıçta kılavuzda bulunan üç sütun yalnızca veri değerlerini (başlık, tür ve yıl) görüntüledi. Bu görüntüyü, veritabanı sütununun adını (örneğin, grid.Column("Title")) geçirerek belirttiniz.

Bu yeni Düzenle bağlantı sütunu farklıdır. Sütun adı belirtmek yerine parametre format geçiriyorsunuz. Bu parametre, sütun verilerini kalın veya yeşil olarak ya da istediğiniz biçimde görüntülemek için yardımcının item işleneceği işaretlemeyi WebGrid değerle birlikte tanımlamanızı sağlar. Örneğin, başlığın kalın görünmesini istiyorsanız, aşağıdaki örneğe benzer bir sütun oluşturabilirsiniz:

grid.Column(format:@<strong>@item.Title</strong>)

(Özelliğinde format gördüğünüz çeşitli @ karakterler, işaretleme ve kod değeri arasındaki geçişi işaretler.)

özelliği hakkında bilgi format edindikten sonra, yeni Düzenle bağlantı sütununun nasıl bir araya getirildiğinden daha kolay anlaşılır:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),

Sütun yalnızca bağlantıyı işleyen işaretlemeden ve satır için veritabanı kaydından ayıklanan bazı bilgilerden (kimlik) oluşur.

İpucu

Bir Yöntem için Adlandırılmış Parametreler ve KonumSal Parametreler

Bir yöntemi çağırıp parametre geçirdiğinizde çoğu zaman parametre değerlerini virgülle ayırarak listelediniz. Aşağıda birkaç örnek verilmiştir:

db.Execute(insertCommand, title, genre, year)

Validation.RequireField("title", "You must enter a title")

Bu kodu ilk gördüğünüzde sorundan bahsetmedik, ancak her durumda, yöntemlere parametreleri belirli bir sırayla geçiriyorsunuz; yani parametrelerin bu yöntemde tanımlanma sırası. ve Validation.RequireFieldsiçindb.Execute, geçirdiğiniz değerlerin sırasını karıştırdıysanız, sayfa çalıştırıldığında bir hata iletisi veya en azından bazı garip sonuçlar alırsınız. Açıkçası, parametreleri geçirmek için sırayı bilmeniz gerekir. (WebMatrix'te IntelliSense parametrelerin adını, türünü ve sırasını öğrenmenize yardımcı olabilir.)

Değerleri sırayla geçirmeye alternatif olarak adlandırılmış parametreleri kullanabilirsiniz. (Parametreleri sırayla geçirme, konumsal parametrelerin kullanılması olarak bilinir.) Adlandırılmış parametreler için, değerini geçirirken parametrenin adını açıkça eklersiniz. Bu öğreticilerde adlandırılmış parametreleri zaten birkaç kez kullandınız. Örnek:

var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3)

ve

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
       grid.Column("Title"),
       grid.Column("Genre"),
       grid.Column("Year")
    )
)

Adlandırılmış parametreler, özellikle bir yöntemin çok sayıda parametre aldığı birkaç durumda kullanışlıdır. Biri, yalnızca bir veya iki parametre geçirmek istediğiniz, ancak geçirmek istediğiniz değerlerin parametre listesindeki ilk konumlar arasında olmadığı durumdur. Bir diğer durum da parametreleri size en anlamlı sırada geçirerek kodunuzu daha okunabilir hale getirmek istemenizdir.

Açıkçası, adlandırılmış parametreleri kullanmak için parametrelerin adlarını bilmeniz gerekir. WebMatrix IntelliSense adları gösterebilir , ancak şu anda sizin için bunları dolduramaz.

Düzenleme Sayfası Oluşturma

Artık EditMovie sayfasını oluşturabilirsiniz. Kullanıcılar Düzenle bağlantısına tıkladığında bu sayfada yer alır.

EditMovie.cshtml adlı bir sayfa oluşturun ve dosyadaki içeriği aşağıdaki işaretlemeyle değiştirin:

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
    @Html.ValidationSummary()
    <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
  </body>
</html>

Bu işaretleme ve kod, AddMovie sayfasındakine benzer. Gönder düğmesinin metninde küçük bir fark vardır. AddMovie sayfasında olduğu gibi, varsa doğrulama hatalarını görüntüleyen bir Html.ValidationSummary çağrı vardır. Doğrulama özetinde hatalar görüntüleneceği için Validation.Messagebu kez çağrısı bırakıyoruz. Önceki öğreticide belirtildiği gibi, doğrulama özetini ve tek tek hata iletilerini çeşitli bileşimlerde kullanabilirsiniz.

öğesinin method özniteliğinin olarak ayarlandığına <form>postyeniden dikkat edin. AddMovie.cshtml sayfasında olduğu gibi bu sayfa da veritabanında değişiklik yapar. Bu nedenle, bu form bir POST işlem gerçekleştirmelidir. (ve işlemleri arasındaki GET fark hakkında daha fazla bilgi için HTML formlarındaki öğreticideki GET, POST ve HTTP Fiil Güvenliği kenar çubuğuna bakın.)POST

Önceki bir öğreticide gördüğünüz gibi, value metin kutularının öznitelikleri önceden yüklemek için Razor koduyla ayarlanıyor. Ancak bu kez, yerine bu görev Request.Form["title"]için ve genre gibi title değişkenler kullanıyorsunuz:

<input type="text" name="title" value="@title" />

Daha önce olduğu gibi, bu işaretleme metin kutusu değerlerini film değerleriyle önceden yükler. Bu kez nesnesini kullanmak yerine Request değişkenleri kullanmanın neden kullanışlı olduğunu birazdan göreceksiniz.

Bu sayfada bir <input type="hidden"> öğe de vardır. Bu öğe, sayfada görünür hale getirmeden film kimliğini depolar. Kimlik başlangıçta bir sorgu dizesi değeri ( veya URL'de benzer bir değer)?id=7 kullanılarak sayfaya geçirilir. Kimlik değerini gizli bir alana koyarak, sayfanın çağrıldığı özgün URL'ye artık erişiminiz olmasa bile form gönderildiğinde kullanılabilir olduğundan emin olabilirsiniz.

AddMovie sayfasının aksine, EditMovie sayfasının kodu iki farklı işleve sahiptir. İlk işlev, sayfa ilk kez görüntülendiğinde ( ve yalnızca o zaman), kodun sorgu dizesinden film kimliğini almasıdır. Kod daha sonra kimliği kullanarak ilgili filmi veritabanından okur ve metin kutularında görüntüler (önceden yükler).

İkinci işlev, kullanıcı Değişiklikleri Gönder düğmesine tıkladığında kodun metin kutularının değerlerini okuması ve bunları doğrulaması olmasıdır. Kodun ayrıca veritabanı öğesini yeni değerlerle güncelleştirmesi gerekir. Bu teknik, AddMovie'de gördüğünüz gibi kayıt eklemeye benzer.

Tek Bir Filmi Okumak için Kod Ekleme

İlk işlevi gerçekleştirmek için bu kodu sayfanın en üstüne ekleyin:

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty()){
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }
}

Bu kodun çoğu, 'i başlatan if(!IsPost)bir bloğun içindedir. ! işleci "değil" anlamına gelir, bu nedenle ifade, bu isteğin gönderim sonrası olup olmadığı anlamına gelir; bu, bu isteğin bu sayfanın ilk kez çalıştırılıp çalıştırılmadığını söylemenin dolaylı bir yoludur. Daha önce belirtildiği gibi, bu kod yalnızca sayfa ilk kez çalıştırıldığında çalıştırılmalıdır. Kodu if(!IsPost)içine almadıysanız, sayfa ilk kez çağrıldığında veya bir düğmeye tıklamaya yanıt olarak her çağrıldığında çalışır.

Kodun bu kez bir blok içerdiğine else dikkat edin. Blokları kullanıma if sunduğumuzda söylediğimiz gibi, test ettiğiniz koşul doğru değilse bazen alternatif kod çalıştırmak isteyebilirsiniz. Burada durum bu. Koşul geçerse (yani, sayfaya geçirilen kimlik uygunsa), veritabanından bir satır okursunuz. Ancak koşul geçmezse blok else çalışır ve kod bir hata iletisi ayarlar.

Sayfaya Geçirilen Değeri Doğrulama

Kod, sayfaya geçirilen kimliği almak için kullanır Request.QueryString["id"] . Kod, kimlik için gerçekten bir değer geçirildiğini sağlar. Hiçbir değer geçirilmezse kod bir doğrulama hatası ayarlar.

Bu kod, bilgileri doğrulamak için farklı bir yol gösterir. Önceki öğreticide yardımcıyla Validation çalıştınız. Doğrulamak için alanları kaydettiniz ve ASP.NET ve kullanarak Html.ValidationMessageHtml.ValidationSummarydoğrulamayı otomatik olarak yaptınız ve hataları görüntülediniz. Ancak bu durumda, kullanıcı girişini gerçekten doğrulamış olmazsınız. Bunun yerine, sayfaya başka bir yerden geçirilen bir değeri doğrulusunuz. Yardımcı Validation bunu sizin için yapmaz.

Bu nedenle, ile if(!Request.QueryString["ID"].IsEmpty()test ederek değeri kendiniz denetlersiniz. Bir sorun varsa, yardımcıda olduğu Validation gibi kullanarak Html.ValidationSummaryhatayı görüntüleyebilirsiniz. Bunu yapmak için çağrısı Validation.AddFormError yapar ve görüntülenmesi için bir ileti iletirsiniz. Validation.AddFormError , zaten aşina olduğunuz doğrulama sistemiyle ilişkili özel iletiler tanımlamanızı sağlayan yerleşik bir yöntemdir. (Bu öğreticinin ilerleyen bölümlerinde bu doğrulama işleminin nasıl daha sağlam hale getirebileceğimizden bahsedeceğiz.)

Film için bir kimlik olduğundan emin olduktan sonra, kod veritabanını okur ve yalnızca tek bir veritabanı öğesi arar. (Büyük olasılıkla veritabanı işlemleri için genel deseni fark etmişsinizdir: veritabanını açın, bir SQL deyimi tanımlayın ve deyimini çalıştırın.) Bu kez SQL Select deyimi içerir WHERE ID = @0. Kimlik benzersiz olduğundan yalnızca bir kayıt döndürülebilir.

Sorgu kullanılarak gerçekleştirilir db.QuerySingle (film listesi için kullandığınız gibi değil db.Query) ve kod sonucu değişkenine row yerleştirir. Ad row rastgeledir; değişkenleri istediğiniz gibi adlandırabilirsiniz. En üstte başlatılan değişkenler film ayrıntılarıyla doldurulur, böylece bu değerler metin kutularında görüntülenebilir.

Düzenleme Sayfasını Test Etme (Şimdiye Kadar)

Sayfanızı test etmek isterseniz , Filmler sayfasını şimdi çalıştırın ve herhangi bir filmin yanındaki Düzenle bağlantısına tıklayın. Seçtiğiniz filmin ayrıntılarının doldurulduğu EditMovie sayfasını görürsünüz:

Filmin düzenlenmesini gösteren Filmi Düzenle sayfasını gösteren ekran görüntüsü.

Sayfanın URL'sinde şuna ?id=10 benzer bir şey (veya başka bir sayı) olduğuna dikkat edin. Şimdiye kadar Film sayfasındaki Düzenle bağlantılarının çalıştığını, sayfanızın sorgu dizesindeki kimliği okuduğu ve tek bir film kaydı almak için veritabanı sorgusunun çalıştığını test ettiniz.

Film bilgilerini değiştirebilirsiniz, ancak Değişiklikleri Gönder'e tıkladığınızda hiçbir şey olmaz.

Filmi Kullanıcının Değişiklikleriyle Güncelleştirmek için Kod Ekleme

EditMovie.cshtml dosyasında, ikinci işlevi uygulamak için (değişiklikleri kaydetmek) aşağıdaki kodu bloğun kapanış ayracı @ içine ekleyin. (Kodu nereye yerleştireceğinizden tam olarak emin değilseniz, bu öğreticinin sonunda görünen Filmi Düzenle sayfasının tam kod listesine bakabilirsiniz.)

if(IsPost){
    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");
    Validation.RequireField("movieid", "No movie ID was submitted!");

    title = Request.Form["title"];
    genre = Request.Form["genre"];
    year = Request.Form["year"];
    movieId = Request.Form["movieId"];

    if(Validation.IsValid()){
        var db = Database.Open("WebPagesMovies");
        var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
        db.Execute(updateCommand, title, genre, year, movieId);
        Response.Redirect("~/Movies");
   }
}

Bu işaretleme ve kod, AddMovie'deki koda benzer. Kod bir if(IsPost) bloktadır, çünkü bu kod yalnızca kullanıcı Değişiklikleri Gönder düğmesine tıkladığında, yani formun ne zaman (ve yalnızca ne zaman) deftere nakledildiği zaman çalışır. Bu durumda, gibi if(IsPost && Validation.IsValid())bir test kullanmazsınız; diğer bir deyişle, AND kullanarak her iki testi birleştirmiş olmazsınız. Bu sayfada, önce bir form gönderimi ()if(IsPost) olup olmadığını belirlersiniz ve sonra alanları doğrulama için kaydedersiniz. Ardından doğrulama sonuçlarını (if(Validation.IsValid()) test edebilirsiniz. Akış AddMovie.cshtml sayfasından biraz farklıdır, ancak etki aynıdır.

Metin kutularının değerlerini ve diğer <input> öğeler için benzer kodları kullanarak Request.Form["title"] alırsınız. Bu kez kodun film kimliğini gizli alandan (<input type="hidden">) aldığına dikkat edin. Sayfa ilk kez çalıştırıldığında kod, kimliği sorgu dizesinden aldı. Sorgu dizesinin o zamandan beri bir şekilde değiştirilmiş olması durumunda, başlangıçta görüntülenen filmin kimliğini aldığınızdan emin olmak için gizli alandan değeri alırsınız.

AddMovie kodu ile bu kod arasındaki en önemli fark, bu kodda deyimi yerine SQL Update deyimini Insert Into kullanmanızdır. Aşağıdaki örnekte SQL Update deyiminin söz dizimi gösterilmektedir:

UPDATE table SET col1="value", col2="value", col3="value" ... WHERE ID = value

Herhangi bir sütunu herhangi bir sırada belirtebilirsiniz ve işlem sırasında Update her sütunu güncelleştirmeniz gerekmez. (Kimliğin kendisini güncelleştiremezsiniz çünkü bu, kaydı yeni bir kayıt olarak kaydeder ve bir işlem için Update buna izin verilmez.)

Not

ÖnemliWhere Kimliğe sahip yan tümcesi çok önemlidir, çünkü veritabanı hangi veritabanı kaydını güncelleştirmek istediğinizi bu şekilde bilir. Yan tümcesini Where bıraktıysanız, veritabanı veritabanındaki her kaydı güncelleştirir. Çoğu durumda bu bir felaket olur.

Kodda, güncelleştirilecek değerler yer tutucular kullanılarak SQL deyimine geçirilir. Daha önce söylediklerimizi tekrar etmek için: Güvenlik nedenleriyle , değerleri BIR SQL deyimine geçirmek için yalnızca yer tutucuları kullanın.

Kod deyimini çalıştırmak Update için kullandıktan db.Execute sonra, değişiklikleri görebileceğiniz listeleme sayfasına geri yönlendirilir.

İpucu

Farklı SQL Deyimleri, Farklı Yöntemler

Farklı SQL deyimlerini çalıştırmak için biraz farklı yöntemler kullandığınızı fark etmiş olabilirsiniz. Birden çok kayıt döndürebilecek bir Select sorgu çalıştırmak için yöntemini kullanırsınız Query . Yalnızca bir veritabanı öğesi döndüreceğini bildiğiniz bir Select sorgu çalıştırmak için yöntemini kullanırsınız QuerySingle . Değişiklik yapıp veritabanı öğelerini döndürmeyen komutları çalıştırmak için yöntemini kullanırsınız Execute .

ve arasındaki QueryQuerySinglefarkta zaten gördüğünüz gibi her biri farklı sonuçlar döndürdüğünden farklı yöntemlere sahip olmanız gerekir. (Yöntemi Execute aslında komutundan etkilenen veritabanı satırlarının sayısı gibi bir değer de döndürür, ancak şimdiye kadar bunu yoksaydınız.)

Elbette, Query yöntem yalnızca bir veritabanı satırı döndürebilir. Ancak, ASP.NET her zaman yönteminin Query sonuçlarını bir koleksiyon olarak ele alır. Yöntem yalnızca bir satır döndürse bile, koleksiyondan bu tek satırı ayıklamanız gerekir. Bu nedenle, yalnızca bir satır geri dönebileceğinizi bildiğiniz durumlarda, kullanmak QuerySinglebiraz daha uygundur.

Belirli türlerdeki veritabanı işlemlerini gerçekleştiren birkaç yöntem daha vardır. Veritabanı yöntemlerinin listesini ASP.NET Web Sayfaları API'sinin Hızlı Başvurusu'nda bulabilirsiniz.

Kimlik Doğrulamasını Daha Sağlam Hale Getirme

Sayfa ilk kez çalıştırıldığında, sorgu dizesinden film kimliğini alırsınız, böylece bu filmi veritabanından alabilirsiniz. Aslında aranacak bir değer olduğundan emindiniz ve bunu şu kodu kullanarak yaptınız:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty()){
        // Etc.
    }
}

Bu kodu, bir kullanıcının Önce Filmler sayfasında film seçmeden EditMovies sayfasına ulaştığında, sayfanın kullanıcı dostu bir hata iletisi görüntüleyeceğinden emin olmak için kullandınız. (Aksi takdirde, kullanıcılar muhtemelen kafalarını karıştıracak bir hata görür.)

Ancak bu doğrulama çok sağlam değildir. Sayfa şu hatalarla da çağrılabilir:

  • Kimlik bir sayı değil. Örneğin, sayfa gibi http://localhost:nnnnn/EditMovie?id=abcbir URL ile çağrılabilir.
  • Kimlik bir sayıdır, ancak var olmayan bir filme başvurur (örneğin, http://localhost:nnnnn/EditMovie?id=100934).

Bu URL'lerden kaynaklanan hataları görmek istiyorsanız Filmler sayfasını çalıştırın. Düzenlenecek filmi seçin ve editMovie sayfasının URL'sini alfabetik bir kimlik veya var olmayan bir filmin kimliğini içeren bir URL olarak değiştirin.

Peki ne yapmalısınız? İlk düzeltme, yalnızca sayfaya geçirilen bir kimlik değil, kimliğin tamsayı olduğundan emin olmaktır. Testin !IsPost kodunu şu örneğe benzer şekilde değiştirin:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
       // Etc.

Teste IsEmpty&& bağlı (mantıksal AND) ikinci bir koşul eklediniz:

Request.QueryString["ID"].IsInt()

ASP.NET Web Sayfaları Programlamaya Giriş öğreticisinde, karakter dizesi gibi AsBoolAsInt yöntemlerin bir karakter dizesini başka bir veri türüne dönüştürdüğünü anımsayabilirsiniz. IsInt yöntemi (ve ve gibi IsBoolIsDateTimediğerleri) benzerdir. Ancak, dönüştürmeyi gerçekleştirmeden yalnızca dizeyi dönüştürip dönüştüremeyeceğinizi test ederler. Burada temelde sorgu dizesi değerinin bir tamsayıya dönüştürülip dönüştürülemediğini söylüyorsunuz....

Diğer olası sorun, var olmayan bir film aramaktır. Film alma kodu şu koda benzer:

var row = db.QuerySingle(dbCommand, movieId);

Yöntemine QuerySingle gerçek filme karşılık gelen bir movieId değer geçirirseniz hiçbir şey döndürülemez ve izleyen deyimler (örneğin, title=row.Title) hatalara neden olur.

Yine kolay bir düzeltme var. db.QuerySingle Yöntem sonuç döndürmezse değişken row null olur. Bu nedenle, değerleri almaya çalışmadan önce değişkenin row null olup olmadığını de kontrol edebilirsiniz. Aşağıdaki kod, değerleri nesneden alan deyimlerin çevresine row bir if blok ekler:

if(row != null) {
    title = row.Title;
    genre = row.Genre;
    year = row.Year;
}
else{
    Validation.AddFormError("No movie was found for that ID.");
}

Bu iki ek doğrulama testiyle sayfa, madde işaretine karşı daha dayanıklı hale gelir. Dalın !IsPost tam kodu artık şu örneğe benzer:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
        movieId = Request.QueryString["ID"];
        var db = Database.Open("WebPagesMovies");
        var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
        var row = db.QuerySingle(dbCommand, movieId);

        if(row != null) {
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else {
            Validation.AddFormError("No movie was found for that ID.");
        }
    }
    else {
        Validation.AddFormError("No movie was selected.");
    }
}

Bu görevin bir blok için iyi bir kullanım olduğuna bir else kez daha dikkat edeceğiz. Testler geçmezse bloklar else hata iletilerini ayarlar.

Son ve yararlı ayrıntılardan biri, Filmler sayfasına bir bağlantı eklemektir. Sıradan olay akışında kullanıcılar Filmler sayfasından başlar ve Düzenle bağlantısına tıklar . Bu, onları filmi düzenleyip düğmeye tıklayabilecekleri EditMovie sayfasına getirir. Kod değişikliği işledikten sonra Filmler sayfasına geri yönlendirir.

Ancak:

  • Kullanıcı hiçbir şeyi değiştirmemeye karar verebilir.
  • Kullanıcı önce Filmler sayfasındaki Düzenle bağlantısına tıklamadan bu sayfaya ulaşmış olabilir.

Her iki durumda da ana listeye geri dönmelerini kolaylaştırmak istiyorsunuz. Bu kolay bir düzeltmedir; işaretlemede kapanış </form> etiketinin hemen arkasına aşağıdaki işaretlemeyi ekleyin:

<p><a href="~/Movies">Return to movie listing</a></p>

Bu işaretleme, başka bir yerde gördüğünüz bir <a> öğe için aynı söz dizimini kullanır. URL, ortalama "web sitesinin kökü" ifadesini içerir ~ .

Film Güncelleştirme İşlemini Test Etme

Artık test edebilirsiniz. Filmler sayfasını çalıştırın ve bir filmin yanındaki Düzenle'ye tıklayın. EditMovie sayfası görüntülendiğinde, film üzerinde değişiklik yapın ve Değişiklikleri Gönder'e tıklayın. Film listesi görüntülendiğinde, değişikliklerinizin gösterildiğinden emin olun.

Doğrulamanın çalıştığından emin olmak için Başka bir film için Düzenle'ye tıklayın. EditMovie sayfasına gittiğinizde Tarz alanını (veya Yıl alanını veya her ikisini) temizleyin ve değişikliklerinizi göndermeyi deneyin. Beklediğiniz gibi bir hata görürsünüz:

Doğrulama hatalarını gösteren Filmi Düzenle sayfası

Değişikliklerinizi bırakmak ve Filmler sayfasına dönmek için Film listesine dön bağlantısına tıklayın.

Sonraki Geliyor

Sonraki öğreticide bir film kaydının nasıl silindiğini göreceksiniz.

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

    if(!Request.QueryString["searchTitle"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
        searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Movies</title>
        <style type="text/css">
          .grid { margin: 4px; border-collapse: collapse; width: 600px; }
          .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
          .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
          .alt { background-color: #E8E8E8; color: #000; }
        </style>
    </head>
    <body>
        <h1>Movies</h1>
          <form method="get">
              <div>
                <label for="searchGenre">Genre to look for:</label>
                <input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
                <input type="Submit" value="Search Genre" /><br/>
                (Leave blank to list all movies.)<br/>
                </div>

              <div>
                  <label for="SearchTitle">Movie title contains the following:</label>
                  <input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
                  <input type="Submit" value="Search Title" /><br/>
                </div>
            </form>

        <div>
             @grid.GetHtml(
                tableStyle: "grid",
                headerStyle: "head",
                alternatingRowStyle: "alt",
                columns: grid.Columns(
                    grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
                    grid.Column("Title"),
                    grid.Column("Genre"),
                    grid.Column("Year")
                )
            )
        </div>
    <p>
        <a href="~/AddMovie">Add a movie</a>
    </p>
    </body>
</html>

Film Sayfasını Düzenle için Tam Sayfa Listesi

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);

            if(row != null) {
                title = row.Title;
                genre = row.Genre;
                year = row.Year;
            }
            else{
                Validation.AddFormError("No movie was selected.");
            }
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }

    if(IsPost){
        Validation.RequireField("title", "You must enter a title");
        Validation.RequireField("genre", "Genre is required");
        Validation.RequireField("year", "You haven't entered a year");
        Validation.RequireField("movieid", "No movie ID was submitted!");

        title = Request.Form["title"];
        genre = Request.Form["genre"];
        year = Request.Form["year"];
        movieId = Request.Form["movieId"];

        if(Validation.IsValid()){
            var db = Database.Open("WebPagesMovies");
            var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
            db.Execute(updateCommand, title, genre, year, movieId);
            Response.Redirect("~/Movies");
        }
    }
}

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
      @Html.ValidationSummary()
      <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
    <p><a href="~/Movies">Return to movie listing</a></p>
  </body>
</html>

Ek Kaynaklar