ASP.NET Core Web API ile NSwag Entegregrasyonu

OpenAPI, Swagger, NSwag nedir ?    OpenAPI insiyatifi, dünya çapında kullanılan Restful API standartlarını tanımlamaya çalışan bir topluluk. Swagger  ise OpenAPI ile tanımlanan WebApiler için oluşturulan spesifikasyon ve üretilen araçlara verilen isim.  Yani geliştirdiğimiz bir Web API için oluşturacağımız swagger spesifikasyon dosyası ile web apimizi dünyaca tanınan bir standarta göre tanımlamış oluyoruz. Bu dosyaya göre istenilen dilde servisimizi kullanacak istemciler yazılabilir. Web API’mizi web servis gibi düşünürsek aslında swagger spesifikasyon dosyaları wsdl’e karşılık geliyor. NSwag, swagger spesifikasyon dosyalarını kullanarak .NET platformu için araçlar üreten kütüphane diyebiliriz. Aşağıda detaylarına gireceğimiz, swagger spesifikasyon dosyasını, Web API önyüzlerini ve C#, TypeScript (Jquery, AngularJS ve Fetch istemcileri) ile ASP.NET Web API controller istemcilerini üretebildiğimiz araç ve kütüphaneleri içeriyor.   VS.NET 2017 ile Örnek Olarak Kullanacağımız Web API Projesinin Oluşturulması   VS.NET 2017 ile Web API şablonunu kullanarak yeni bir ASP.NET Core web uygulaması projesi oluşturup derleyip varsayılan olarak gelen Values Web API’sini deneyebiliriz. Values Apisinin Get metodunu tarayıcıdan çağırdığımızda aşağıdaki gibi basit bir JSON döndüğünü görüyoruz. Bunu makalemizdeki örneklerimizde kullanıyor olacağız.      Web API Metodlarını İncelemek ve Test Etmek   Gerek kendi yazdığım, gerekse başka sağlayıcılarca sağlanan web api metodlarını incelemek test etmek için yakın zamana kadar Postman kullandım. Kullanıcı dostu arayüzü ve tarihçe özelliği ile web api testlerinde ve hatta .NET Click Once uygulamaların manifesto dosyalarını inceleme konusunda olmazsa olmaz bir araç benim için. Örnek olarak hazırladığımız projeyi Postman ile aşağıdaki gibi test edebiliyoruz. Http metodunu değiştirerek, parametre var ise onları da girerek oldukça hızlı bir şekilde web api testi yapabiliyoruz.   Swagger UI ile Web API projemize oluşturacağımız önyüzler açıkçası Postman gibi bir araca ihtiyacı yok edecek gibi gözüküyor. Fazla vakit kaybetmeden projemizin NSwag entegrasyonunu tamamlayıp web api metodlarımız için oluşacak önyüzleri inceleyelim.   ASP.NET Web API Projesi NSwag Entegrasyonu   Hazırladığımız Web API uygulamasının swagger spesifikasyonu oluşturmak için öncelikle yapmamız gereken şey uygulamamıza NSwag.AspNetCore referansını eklemek. Web API projesine nuget ile NSwag.AspNetCore referansı eklenerek NSwag projeye dahil edilmiş oluyor. Aşağıdaki ayarları yaparak Swagger Ui’i aktif hale getirerek Web API metodlarımız için hazırlanan Swagger önyüz ekranlarına ulaşabilir ve tarayıcı yardımı ile metodlarımızı test edebilir hale geliyoruz. Bu uygulayacağımız metodlar NSwag’in her versiyonunda değişikliğe uğramış görülüyor. Internetteki pek çok örnekte kullanılan metodlar obsolete olarak işaretlenmiş, kullanımı tavsiye edilmiyor, bu metodların yerlerine yeni metodlar eklenmiş kütüphanede. Fakat pek çoğunun dökümantasyonunu yada güncel bir örneğini bulmak çok zor. Açıkçası deneme yanılma ile Swagger Ui ekranlarını aktif hale getirebildim.      NSwag.AspNetCore referansını projemize ekledikten sonra aşağıdaki gibi swagger ui entegrasyonunu yapıyoruz. public void ConfigureServices(IServiceCollection services) { services.AddSwaggerDocument(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseSwagger(); app.UseSwaggerUi3(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }     Yukarıda gördüğünüz gibi NSwag hem swagger spesifikasyon osyasını oluşturuyor, hem de uygulamamız altındaki web apiler için dökümantasyon ve test arayüzleri oluşturuyor.     NSwagStudio ile Web Api'mize Erişecek İstemci Kodunu Üretelim   Şuana kadarki örneklerimizde ASP.NET Core Web API ile hazırladığımız Web API'mize tarayıcı izlenebilen bir dökümantasyon sayfası üretip test edebileceğimiz önyüzleri nasıl oluşturabileceğimiz üzerinde durduk. Yani konuya sunucu tarafından, api sağlayıcı tarafından baktık. Şimdiki örneğimizde konuya istemci tarafından yani ilk örneğimizde sağladığımız web apiyi kullanacak uygulama tarafından bakacağız. NSwag  Studio Studio uygulaması ile Web Api projemizde oluşturulan swagger.json dosyası analiz ettirilerek C#, TypeScript veya C# Web Api controller’ı şeklinde API’yi kullanan client kodların üretilmesi sağlanabilir. Studio projesi onlarca seçenek ile özelleştirilebiliyor ve oldukça parametrik gözüküyor. Aşağıdaki örnekte kendi yazdığım iki web api için oluşturulan C# istemci kodunu nasıl ürettiğimi ve kullanımın nasıl olduğunu inceleyebiliriz.           CustomerClient cusClient = new CustomerClient(new System.Net.Http.HttpClient()); List<Customer> customers = (List<Customer>)cusClient.GetAsync().GetAwaiter().GetResult(); foreach (Customer value in customers) { Console.WriteLine("Customer received : {0} {1}", value.Name, value.Surname); }   NSwag Studio sadece Windows GUI olarak değil, aynı zamanda komut satırı uygulaması olarak da kullanılabiliyor. Böylece derleme otomasyonumuz içerisine script olarak kod üretimini dahil edip, kullanacağımız istemci sınıfları otomatize bir şekilde güncel tutabiliriz. Tam da bu amaçla eklenmiş Cake ve MSBuild scriptleri desteği mevcut. Kaynaklar   Bu örnekleri hazırlarken internette karşılaştığım çoğu kaynak eski kalmıştı, örnek olarak verilen neredeyse tüm kod parçaları kütüphaneden kaldırılmış ya da obsolete olarak işaretlenmişti. An itibariyle çalışır durumdaki metodlar makalemdeki metodlardır. Projeyi güncelledikçe makalemi de güncelliyor olacağım. Makaleyi hazırlarken aşağıdaki kaynaklardan faydalandım. Daha güncel ve orjinal dilindeki kaynaklara buradan erişebilirsiniz. https://github.com/RSuter/NSwag https://blog.rsuter.com/nswag-tutorial-integrate-the-nswag-toolchain-into-your-asp-net-web-api-project/

ASP.NET 5 / ASP.NET MVC 6 View Components Yeniliği - Görsel Bileşenler

 Frameworklerin yeni versiyonlarında sıklıkla mevcut bileşenler tekrar kullanılabilirlik açısından ele alınır ve iyileştirmeler yapılır. ASP.NET 5 ve ASP.NET MVC 6.0 ile partial view ve child action özellikleri ele alınıp view components ile daha tekrar kullanılabilir hale getirilmiş. Tekrar kullanılabilir bir taslak yaratmak için controller'a bağımlılık ortadan kaldırılmış ve asenkron olarak kullanabilme sağlanmış. Bu yazımda öncelikle child action ile tekrar kullanılabilir bir görsel taslak hazırlamaya çalışıp, sonra bu örneği view components ile hazırlayıp kullanmaya çalışacağız.   ASP.NET MVC 2 Child Actions ile tekrar kullanılabilir bileşenler Child Actions konusuna hakim okuyucular bu bölümü atlayıp bir sonraki bölüme devam edebilir. ASP.NET MVC 2 ile gelen Child Actions sayesinde controllerlarımıza tanımladığımız aksiyonları ChildActionOnly attribute'u ile işaretleyip, istediğimiz görsel taslak içerisinde çağırabiliyoruz. Böylece DRY prensibine uygun olarak aksiyonu ve görselini uygulamamız içerisinde defalarca kullanabiliyoruz. Aşağıda child action olarak tanımladığımız bir aksiyonu ve görsel taslağını inceleyebiliriz :  public class HomeController : Controller { public ActionResult Contact() { return View(); } [ChildActionOnly] public ActionResult Movies() { List<Movie> movieList = new List<Movie>(); movieList.Add(new Movie() { ImdbId = "tt0470752", Name = "Ex Machina" }); movieList.Add(new Movie() { ImdbId = "tt2562232", Name = "Birdman" }); movieList.Add(new Movie() { ImdbId = "tt0137523", Name = "Fight Club" }); return View(movieList); } } Görsel taslak dosyası : Movies.cshtml  @model List<ViewComponentsTrial.Models.Movie> <div>Movies : </div> <ul> @foreach(var item in Model) { <li><a href="http://www.imdb.com/title/@item.ImdbId">@item.Name</a></li> } </ul> Yukarıda hazırlamış olduğumuz tekrar kullanılabilir child action örneğini uygulamamız içerisinde aşağıdaki gibi kullanabiliyoruz :  @Html.Action("Movies") View Component'in Hazırlanması ve Kullanılması Yukarıdaki örnekte child action yardımı ile hazırladığımız film listesini, uygulamamız genelinde kullanılabilecek bir View Component olarak hazırlamak istersek aşağıdaki gibi ViewComponent sınıfından türeyen bir sınıf hazırlamamız gerekiyor. public class MoviesViewComponent : ViewComponent { public IViewComponentResult Invoke(string imdbId) { List<Movie> movies = GetMovies(); if (string.IsNullOrEmpty(imdbId)) { return View(GetMovies()); } else { return View(GetMovies().Where(m => m.ImdbId == imdbId)); } } public List<Movie> GetMovies() { List<Movie> movieList = new List<Movie>(); movieList.Add(new Movie() { ImdbId = "tt0470752", Name = "Ex Machina" }); movieList.Add(new Movie() { ImdbId = "tt2562232", Name = "Birdman" }); movieList.Add(new Movie() { ImdbId = "tt0137523", Name = "Fight Club" }); return movieList; } }   View Component olarak hazırladığımız sınıfların isminin ViewComponent şeklinde bitmesi gerekiyor. View component'imiz Invoke metodu ile görsel taslakta kullanılacak modeli dönüyor. Hazırladığımız view component'in görsel taslağını aşağıdaki gibi hazırlıyoruz. Burada dikkat edilmesi gereken nokta, görsel taslağın konumlandığı dizin. Görsel taslağımız ~\Views\Shared\Components\Movies dizininde bulunuyor. Yani kullanılmak istenen controller'ın sahip olduğu görsel taslak dizininin altında Components dizini oluşturup bunun altına view componentimiz için bir dizin oluşturmamız gerekiyor. Bu dizinde görsel taslağımızı Default.isml ismi ile kaydediyoruz. Ben örnek olarak kullandığım view component'i tüm görsel taslaklarda kullanabilmek için shared dizini altına konumlandırdım. Dilersek view component diğer dizinler altına konumlanıp sadece konumlandığı dizin altında kullanılması da sağlanabilir. Görsel taslağımıza göz atarsak : @model IEnumerable<ASP_NET_5_TagHelpers.Models.Movie> <div>Movies : </div> <ul> @foreach (var item in Model) { <li><a href="http://www.imdb.com/title/@item.ImdbId">@item.Name</a></li> } </ul> Şimdi hazırladığımız view component'i kullanmak için yapmamız gereken tek şey sayfalarımızda aşağıdaki gibi çağırmak : @Component.Invoke("Movies", "") // Asenkron kullanım : @await Component.InvokeAsync("Movies", "") // Parametreli kullanım : @await Component.InvokeAsync("Movies", "tt2562232") Sonuç View components, ASP.NET içerisindeki görsel taslakları yeniden kullanılabilir yapmak için getirilmiş ve önceki tekniklere göre çok daha etkili bir teknik. Sadece controller bağlantısının koparılması bile tekrar kullanılabilirlik açısından tercih sebebi olmasını sağlayacaktır. Örneğimde yer alan kod bloklarına ve dosyalara aşağıdaki github projesi ile ulaşabilirsiniz :  View Components Örnekleri  

ASP.NET 5 Tag Helpers - Etiket Yardımcıları

ASP.NET MVC ile Razor View Engine ilk çıktığında HTML helpers ile tanıştık ve MVC projelerinde yoğun olarak HTML Helper metodlarını kullandık, kullanımı kolaylaştırmak için kendi yardımcı metodlarımızı yazdık. ASP.NET MVC ile alakalı pek çok soru ve takıldığımız pek çok nokta HTML Helper kullanımı ile alakalı oldu. HTML'nin basitliğinden ve yıllardır tecrübe ettiğimiz etiketler ile attributelerden uzaklaştık. Yerine HTML Helper metodlarına geçilen parametrelerle boğuşmaya başladık. Şahsen hala ASP.NET MVC'de HTML Helper ile oluşturacağım bir linke class attribute'u verirken zorlanmıyor değilim. İşte bu noktada Tag Helpers - etiket yardımcıları ile biz geliştiricilerin yardımına biraz geçte olsa yetişilmiş oldu. Tag Helpers temelde bize kullanım kolaylığından başka yeni bir şey sunmuyor. Razor HTML yardımcıları ile yazabildiğimiz kodu, tag helpers ile daha markup diline yakın olarak yazabiliyoruz, View'larımız daha okunabilir oluyor. Dolayısıyla anlaması ve geliştirmesi daha kolay hale geliyor. ASP.NET 5 ile gelen etiket yardımcılarına ek olarak istersek kendi etiket yardımcılarımızı geliştirebiliyoruz, ki bu kısım bence konunun en heyecan veren yeri. Bu yazıda öncelikle ASP.NET 5 ile gelen varsayılan etiket yardımcılarına değinip, sonrasında kendi etiket yardımcımızı nasıl yazacağımız ve kullanacağımız üzerinde durmaya çalışacağım.   ASP.NET 5 Varsayılan Etiket Yardımcıları Aşağıdaki kod bloğunda etiket yardımcıları olmadan HTML yardımcıları yardımı ile basit bir view örneği görüyoruz. Buradaki HTML yardımcıları ile oluşturduğumuz üç elemana dikkat edelim. Bir textbox, bir checkbox ve bir link elemanı oluşturuyoruz.   @model ASP_NET_5_TagHelpers.Models.ToDoListItem <label>Açıklama : </label> @Html.TextBoxFor(m => m.Text) <br /> <label>Tamamlandı mı ? : </label> @Html.CheckBoxFor(m => m.IsCompleted, new { id = "todolistitem" + Model.ItemId }) <br /> @Html.ActionLink("Tag Helper Kullanılmış Sayfaya Git", "WithTagHelper", "Home")    Şimdi aynı örneği ASP.NET 5 ile gelen varsayılan etiket yardımcıları ile yapalım. ASP.NET 5 ile gelen varsayılan etiket yardımcılarını kullanmak için yapmamız gereken tek şey @addTagHelper emri ile etiket yardımcılarının bulunduğu assembly'i referans göstermek. Böylece aşina olduğumuz HTML etiketlerine etiket yardımcıları ile gelen ek attibute'ları kullanarak view'ımızı hazırlayabiliyoruz.    @model ASP_NET_5_TagHelpers.Models.ToDoListItem @addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers" <label>Açıklama : </label> <input type="text" asp-for="Text" /><br> <label>Tamamlandı mı ? : </label> <input type="checkbox" asp-for="IsCompleted" id="@String.Format("todolistitem{0}", Model.ItemId)" /><br /> <a asp-controller="Home" asp-action="WithoutTagHelper">Tag Helper Kullanılmamış Sayfaya Git</a>  Örnekte bulunan input elemanlarına tanımladığımız asp-for attributelarına dikkat edelim. Bunlar elemanın, modelin hangi özelliği ile eşleşeceğini belirtiyor. Link elemanına gelen asp-controller ve asp-action attributelarına dikkat edelim, bunlar da link elemanının hangi controller'ın hangi aksiyonu çalışacağını belirtiyoruz. İşler oldukça basitleşmiş ve okunabilir hale gelmiş değil mi ?  Kendi Etiket Yardımcımızı Geliştirelim  ASP.NET 5 ile gelen varsayılan etiket yardımcılarının yanı sıra kendi etiket yardımcımızı yazabilmemizi sağlayan sınıflar da mevcut. Microsoft.AspNet.Razor.Runtime.TagHelpers isim alanı altındaki TagHelper sınıfından türeteceğimiz sınıflar vasıtasıyla kendi etiket yardımcımızı geliştirebiliyoruz. Sınıfın public özellikleri view'da kullanacağımız elemanın attibutelarına karşılık geliyor. Process metodu içerisinde ise sayfamız istemciye gönderilirken nasıl render edilmesini istiyorsak öyle HTML elemanları tanımlayarak çıktımızı üretebiliriz. Örneğin aşağıdaki Bootstrap input group örneğini ele alalım.  <div class="input-group"> <input type="text" class="form-control" placeholder="Recipient's username" aria-describedby="basic-addon2"> <span class="input-group-addon" id="basic-addon2">@@example.com</span> </div>  Bu kod bloğunu, tekrar kullanılabilir bir etiket yardımcısına aşağıdaki gibi çevirebiliriz. InputGroupTagHelper sınıfının Id ve Domain özelliklerine dikkat edin. Bunları daha sonra view dosyamızda attribute olarak kullanacağız. public class InputGroupTagHelper : TagHelper { public string Id { set; get; } public string Domain { set; get; } public override void Process(TagHelperContext context, TagHelperOutput output) { // Outer Tag : output.TagName = "div"; output.Attributes.Add("class", "input-group"); // Inner Input : var name = new TagBuilder("input"); name.MergeAttribute("type", "text"); name.MergeAttribute("class", "form-control"); name.MergeAttribute("placeholder", "Recipient's username"); name.MergeAttribute("aria-describedby", this.Id); // Span : var span = new TagBuilder("span"); span.MergeAttribute("class", "input-group-addon"); span.MergeAttribute("id", this.Id); span.InnerHtml = this.Domain; output.Content.SetContent(name.ToString() + span.ToString()); } } Tanımladığımız etiket yardımcısını view dosyasında aşağıdaki gibi kullanabiliriz :  @addTagHelper "*, ASP_NET_5_TagHelpers" <input-group id="basic-addon2" domain="@@gmail.com"></input-group>       Sonuç Bu yazımda ASP.NET 5 ile gelen tag helpers - etiket yardımcılarını incelemeye çalıştık. Şuan ASP.NET 5 Beta versiyonu olduğu için kod örneklerinde eklemeler ve çıkarmalar olabilir. Hatta bazı HTML elemanlarında varsayılan etiket yardımcılarının istenen şekilde çalışmadığını gördüm. Final sürümünde daha stabil olacaktır. Yazımda bahsettiğim örneklere aşağıdaki github linkinden ulaşabilirsiniz. ASP.NET 5 TagHelpers Örnekleri  

"DNX SDK version 'dnx-clr-win-x86.1.0.0-beta5' failed to install" hatası ve çözümü

Visual Studio 2015 ile ASP.NET 5'e gelen yeni özellikleri incelemek üzere ilk ASP.NET 5 projenizi açtığınız ve derleyip çalıştırmaya çalıştığınız anda tüm hevesinizi söndüren bu hatanın temelinde aslında .NET Framework'e gelen yeni bir özellik sebep oluyor.   DNX SDK version 'dnx-clr-win-x86.1.0.0-beta5' failed to install. The solution will use DNX SDK version ‘dnx-clr-win-x86.1.0.0-beta5’ for this session.   Bu hata, .NET Framework Version Manager tarafından yüklenmeye çalışılan, ASP.NET 5'i içeren .NET Execution Environment (DNX) SDK'sının yüklenmesi sırasında alınan bir hata. Sebebi Windows 7'de Powershell 3.0 versiyonunun kurulu olmamasından kaynaklı. Bu hata ile ilgili detaylar Microsoft destek sayfasında mevcut. PowerShell'in hangi versiyonuna sahip olduğumuzu görmek için powershell komut satırına aşağıdaki komutu yazıp görebiliriz. $PSVersionTable PowerShell 3.0 versiyonunu kurmak için Microsoft'un PowerShell 3.0 Download sayfasından güncellemeyi indirip kurulumu yaptıktan sonra komut satırında şunu görüyor olmalıyız :  PowerShell'i 3.0 veya daha üst versiyona yükselttikten sonra projeyi yeniden açıp ve derleyince işlemin biraz uzun sürdüğünü ve output penceresini açarsanız ASP.NET 5'i kullanabilmek için ihtiyaç duyduğumuz DNX versiyonunun indirilip yüklendiğini göreceksiniz. Komut satırını açıp dnvm list komutu ile makinanızda kurulu DNX versiyonlarını listelerseniz aşağıdakine benzer bir çıktı ile karşılaşırız. Dilersek yine dnvm komutlarını kullanarak ihtiyacınız olan DNX versiyonlarını makinamıza kurabiliriz.  

IBundleOrderer İle Bundle İçerisindeki Dosyaların Sıralanması

Geçtiğimiz haftalarda incelediğim Bundling ve Minification yazısında bir dizin içerisindeki kaynak dosyalarımızı joker karakterler ile bir bundle haline getirip sayfamıza ekleyebileceğimizden bahsetmiştik. Bu dizin içerisindeki tüm dosyalar alfabetik sırada bundle içerisinde işlenir ve referans olarak verilen yerlerde bu sıralamada istemciye sunulur. Çoğu zaman bu tercih edilen bir durum değildir. Bazı temel script dosyalarımızın sayfamızda öncelikli olarak referans verilmesini isteriz. Bu temel script dosyalarını kullanan diğer script dosyalarımız ise sonrasında sayfamıza eklenir. İşte bu kurduğumuz hiyerarşik yapıyı oluşturacağımız bundle'lar içerisinde de yapabilmemiz için ya dosya isimlerini alfabetik olarak yarattığımız hiyerarşiye uyacak şekilde hazırlamamız gerekir ya da IBundleOrderer kullanarak bundle içerisindeki dosyalarımızı sıralayacak bir mekanizma oluşturabiliriz.  Bu yazımda IBundleOrderer interface'ini inceleyerek, basit bir örnek ile bundle içerisindeki script dosyalarımızın hiyerarşisini web.config dosyası içerisinde tanımlayacağımız bir parametre ile yönetmeyi deneyeceğiz.   IBundleOrderer interface'i ve Bundle içerisindeki dosyaların sıralanması Uygulamamız içerisinde oluşturduğumuz Bundle'ların özellikleri arasında Orderer adında bir özellik ile Bundle'ımıza dosyalarını sıralayabileceğimiz bir IBundleOrderer interface'ini uygulayan bir sınıf verebiliyoruz. Bundle myBundle = new Bundle("~/bundles/SiteScripts", new JsMinify()); myBundle.IncludeDirectory("~/Scripts/SiteScripts", "*.js"); myBundle.Orderer = new MyBundleOrderer(); bundles.Add(myBundle); Eğer IBundleOrderer interface'ine gözatarsak eğer OrderFiles metodu ile bundle içerisindeki dosyaları sıralayacak bir metod içeren bir interface olduğunu görüyoruz. Bundle oluşturulurken içerisindeki dosyaları parametre olarak gönderip, dönüş parametresi olarak da sıralanmış dosyaların listesini içeren bir kolleksiyon bekleniyor  :  namespace System.Web.Optimization { public interface IBundleOrderer { IEnumerable<System.IO.FileInfo> OrderFiles(BundleContext context,  IEnumerable<System.IO.FileInfo> files); } } Şimdi yukarıdaki örneğimizde kullandığımız ve IBundleOrderer interface'ini uygulayan sınıfımıza gelecek olursak :  public class MyBundleOrderer : IBundleOrderer { public IEnumerable<System.IO.FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { if (ConfigurationManager.AppSettings["HighPriorityScripts"] != null) { string[] highPriorityScripts = ConfigurationManager.AppSettings["HighPriorityScripts"].Split(','); List<FileInfo> listFiles = new List<FileInfo>(files); List<FileInfo> orderedFiles = new List<FileInfo>(); foreach (string highPriorityFile in highPriorityScripts) { FileInfo nextFileInfo = listFiles.Find(delegate(FileInfo arg) { return arg.Name == highPriorityFile; } ); if (nextFileInfo != null) { orderedFiles.Add(nextFileInfo); } } foreach (FileInfo lowPriorityFile in listFiles) { if (!orderedFiles.Contains(lowPriorityFile)) { orderedFiles.Add(lowPriorityFile); } } return orderedFiles; } return files; } }   <!-- Virgülle ayrılmış script dosyaları --> <add key="HighPriorityScripts" value="Z_HighPriorityScript.js,SmallJSFile.js" />   MyBundleOrderer sınıfı web.config'de yukarıdaki gibi tanımlayacağımız HighPriorityScripts parametresini alıp, öncelik verilecek script dosyalarını belirleyip dönüş yapılacak listeye öncelikli olarak bu dosyaları ekliyor. Sonrasında geriye kalan dosyalar dönüş listesine ekleniyor ve oluşturulan sıralı liste dönülüyor. Böylece bundle'ımız içerisindeki dosyalarımızı web.config dosyasındaki parametremiz ile önceliklendirerek yönetebilir hale gelmiş oluyoruz.