WebForms’un Yeniden Doğuşu: Razor Pages

Razor Pages, asp.net core 2 ile birlikte gelen yeni bir özellik. Daha önce kullandığımız asp.net web forms çatısına yaklaşım olarak benzemekle birlikte klasik asp.net webforms’u kullanmadan asp.net mvc üzerine geliştirilmiştir. Razor Pages, sayfa bazlı senaryolar için bildiğimiz mvc (model view controller)’a göre daha kolay uygulama geliştirmeyi sağlayan bir platformdur. Frontend çatılarda kullanılan yaklaşım olan mvvm (model view view model) yapısına benzeşen çift yönlü bağlantı (two way binding) özelliğini desteklemektedir.

Razor Pages’in tek sorumluluk prensibine (single responsibility) uygun bir yaklaşımı var. Öncelikle basit bir html sayfa geliştirmek için daha az dosya kullanılıyor ve dosya hiyerarşisi daha basit. Bildiğiniz gibi genel olarak dotnet web uygulaması geliştirmek için kullandığımız asp.net mvc çatısında controller’in içerisinde pek çok sayfa ile ilgili actionlar vardı. Controller’a bağlı tüm sayfaların actionlarını tek bir dosyada tutuyorduk. Bu durumda controller dosyası büyüyor böylece kodun okunurluğu azalıyor ve mental bir karmaşa yaratıyordu. Çok sayfalı web uygulamaları için bu bir handikap aslında.

Razor Pages bu yönüyle bir avantaj sağlıyor. Mvc yapısı üzerinde geliştirildiği için, mvc de var olan herşeyi destekliyor. (Routing, ModelState vs…). Sözkonusu yapı bize daha önce webforms’ta olup ta istemediğimiz viewstate gibi yapılardan arındırılmış, kompakt bir dosya hiyerarşisi ile birlikte hızlı ve pratik uygulama geliştirmeye yönelik bir çatı sunuyor.

Razor Pages’i mvc ile karşılaştıracak olursak, sayfa ile ilgili olmak kaydıyla controller ve model (viewmodel) objesinin PageModel’e dönüşmüş hali diyebiliriz. Örnek uygulama geliştirirken farkı daha iyi anlayacağız.

Örnek Uygulama

Webforms daki codebehind yaklaşımında olduğu gibi html sayfalarına bağlı bir PageModel sınıfı oluşturuyoruz. İstersek kodlarımızı direkt sayfaya functions diyerek yerleştirebiliriz. Fakat önerilen yaklaşım ayrı bir pagemodel dosyası oluşturmak. Biz iki şeklini de örneklerimizde göstereceğiz.

Visual Studio 2017 ile bir razor pages uygulaması yapalım. Razor Pages uygulaması geliştirmek için, sistemimizde asp.net core 2 versiyonunun kurulu olması gerekiyor.

Daha sonra da asp.net core 2.0 ile birlikte Web Application seçeneğinin seçili olması gerekiyor.

Visual Studio öntanımlı şablona göre bize bir proje yapısı oluşturmuş oldu.

Solution explorer’a baktığımızda mvc’den farklı olarak controller ve model dizinlerinin olmadığını görürüz. Onun yerine Pages diye bir dizinin oluşturulduğunu ve Index.cshtml’a bağlı bir c# sınıfının oluşturulduğunu görürüz (CodeBehind: Index.cshtml.cs).

Visual Studio’nun oluşturduğu dosyaları kullanmayalım ve kendi dosyamızı oluşturalım. Pages dizinine sağ tıklayarak, Add Razor Page diyelim (Ornek1).

Ornek1’imiz PageModel dosyası oluşturmasın ve Layout kullanmasın. Resimde gördüğünüz gibi ekleyelim:

Ornek1.cshtml:
@page
@{
    Layout = null;
}
@model Ornek1Model
@using Microsoft.AspNetCore.Mvc.RazorPages
@functions {
public class Ornek1Model : PageModel
{
    public string Mesaj { get; private set; } = "";
    public void OnGet()
    {
        Mesaj += "Merhaba Dünya";
    }
}
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Ornek1</title>
</head>
<body>
    <p>@Model.Mesaj</p>
</body>
</html>

Projeyi F5 ile çalıştırdığımızda Index sayfası açılarak varsayılan olarak. Bunu değiştirmek istiyoruz, Index yerine Ornek1 sayfası açılsın. Bunun için Startup.cs dosyasını değiştirelim.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace RazorPagesDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
                .AddRazorPagesOptions(options => {
                    options.Conventions.AddPageRoute("/Ornek1", "");
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action=Index}/{id?}");
            });
        }
    }
}

Hata almamak için Index.cshtml dosyasını seçip silelim.

Tekrar çalıştıralım

İkinci örneğimizde PageModel sınıfını ayrı bir dosyada oluşturalım. Tekrar Pages dizinine sağ tıklayarak Add -> Razor Page diyelim. Bu sefer Generate PageModel class seçeneği işaretli olsun.

Ornek2.cshtml:
@page
@model RazorPagesDemo.Pages.Ornek2Model
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Ornek2</title>
</head>
<body>
    <h2>Ornek 2</h2>
    <p>@Model.Mesaj</p>
</body>
</html>

Ornek2.cshtml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesDemo.Pages
{
    public class Ornek2Model : PageModel
    {
        public string Mesaj { get; private set; } = "";
        public void OnGet()
        {
            Mesaj += "Merhaba Dünya";
        }
    }
}

Startup.cs dosyasında default route özelliğini Ornek2 olarak değiştirip çalıştıralım:

Bonus: Ajax İşlemleri

Mvc uygulaması geliştirirken, javascript ajax metodları geliştirmek için controller’a action metodları yazıyorduk. Razor Pages için bu işlemi nasıl yapacağımızı görelim.

Ajax metodlarını çağırabilmemiz için bir takım ayarlamalar yapmamız gerekiyor.

Standart PageModel kodlarında metodların belirli bir deseni var. İşleyici metodlar (Handler method) standart http metodlarına benziyor.

Örneğimizde kullandığımız OnGet metodu sayfa yüklenirken kullanılıyor. OnPut metodu form post edilirken kullanılır. Farklı desende bir metod kullanmamız gerektiği zaman handler set etmemiz gerekiyor.  Örneği yazdığımızda bu konuyu daha iyi anlayacağız.

Diğer bir konu da güvenlik gerekçesiyle metod üzerinde ValidateAntiForgeryToken özelliğinin aktif edilmesi ve ajax metod çağrılarında xsrf token’ının header kısmında gönderilmesi gerekiyor.

Header’la ilgili değişikliğin geçerli olması için Startup.cs dosyasında değişiklik yapalım.

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
       services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
       services.AddMvc()
               .AddRazorPagesOptions(options => {
                    options.Conventions.AddPageRoute("/Ornek2", "");
               });
}

Ornek2.cshtml.cs dosyasına yeni bir metod ekleyelim. Method müşteri listesini dönüyor olsun.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesDemo.Pages
{
    public class Ornek2Model : PageModel
    {
        public string Mesaj { get; private set; } = "";

        public void OnGet()
        {
            Mesaj += "Merhaba Dünya";
        }

        [ValidateAntiForgeryToken]
        public JsonResult OnGetMusteriler()
        {
            List<string> lstString = new List<string>
            {
                "Ali",
                "Veli",
                "Ayşe"
            };
            return new JsonResult(lstString);
        }
    }
}

Ornek2.cshtml dosyasına da jquery kütüphanesini ekleyerek, ajax fonksiyonumuzu oluşturalım.

@page
@model RazorPagesDemo.Pages.Ornek2Model
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Ornek2</title>
</head>
<body>
    <h2>Ornek 2</h2>
    <p>@Model.Mesaj</p>
    <div>
        <form method="get">
            <textarea id="musterilist" cols="50" rows="10">
            </textarea>

            <div>
                <button id="btnAjax">Test Ajax</button>
            </div>
        </form>
    </div>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script>
        $(function () {
            $('#btnAjax').on('click', function (e) {
                e.preventDefault();
                $.ajax({
                    url: '/Ornek2?handler=Musteriler',
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN",
                            $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    success: function (data) {
                        console.log('success');
                        $('#musterilist').val(data);
                    }
                });
            });
        });
    </script>
</body>
</html>

Ajax metodunu çağırabilmemiz için, butonun form içerisinde olması gerekiyor. Buna dikkat etmemiz gerekiyor. Jquery ajax metodunda url olarak gönderdiğimiz şekli de dikkatinize sunuyorum arkadaşlar: ‘/Ornek2?handler=Musteriler’

Butona tıkladığımız zaman ajax ile bize müşteri listesini dönecektir.

 

 

 

 

 

 

 

Yorum Gönder

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Scroll to Top