Url Nasıl Kısaltılır
Selamlar;
Bugün aynı yada ‘da olduğu gibi Url kısaltan bir web uygulaması yazacağız. Tabi bunu tamamen benim fikir ve hayal gücüme göre yapacağız. İzlediğim yola alternatif fikri olanlar lütfen paylaşmaktan çekinmesin.
Öncelikle kısaltılacak Url’in tutulacağı “Urls” tablosunu aşağıdaki gibi oluşturalım. Database’imizin adı da ShortUrl olsun. Arama işlemi ShortUrl’e göre yapıldığı için Primary Index ShortUrl’dir.
Solution’a bir DAL projesi eklenip, var olan Database üzerinden CodeFirst ile ilgili Poco ve DbContext nesneleri aşağıdaki gibi yaratılır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
namespace DAL { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.Spatial; public partial class Urls { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } [StringLength(1000)] public string Url { get; set; } [Key] [StringLength(10)] public string ShortUrl { get; set; } } } namespace DAL { using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; public partial class UrlContext : DbContext { public UrlContext() : base("name=UrlContext") { } public virtual DbSet<Urls> Urls { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Urls>() .Property(e => e.Url) .IsUnicode(false); modelBuilder.Entity<Urls>() .Property(e => e.ShortUrl) .IsUnicode(false); } } } |
Şimdi sıra geldi bir Mvc projesi yaratıp girilicek uzun url’i kısaltıp database’e kaydetmeye.
Öncelikle HomeController.cs’e aşağıdaki action yazılır:
1 2 3 4 |
public ActionResult Shorter() { return View(); } |
RouteConfig.cs aşağıdaki gibi değiştirilir: Amaç sayfaya url girilmeden ilk gelindiğinde default olarak “Shorter” view’ına gelinmesidir.
1 2 3 4 5 |
routes.MapRoute( name: "Default", url: "{controller}/{action}", defaults: new { controller = "Home", action = "Shorter" } ); |
Shorter.cshtml: “shortenerInputText” input alanına kısaltılması istenen uzun “Url” girilir. “URL Kısalt” buttonuna basılınca “shorUrl()” function’ı ilgili kısaltılacak Url’i alıp “/Home/ShortUrl” action’ına post eder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Shorter</title> <link href="~/Content/main.css" rel="stylesheet" /> <script src="~/Scripts/jquery-2.1.4.min.js"></script> <script> function shortUrl() { var longUrl = $('#shortenerInputText').val(); $.post('/Home/ShortUrl', { Url: longUrl }, function (data) { $('#result').html("http://localhost:7461/" + data); //$('#shortID').show(); }); } </script> </head> <body> <div class="IXTYPID-r-e IXTYPID-i-c"> <div class="IXTYPID-t-a IXTYPID-a-a" aria-hidden="true" style="display: none;"><div class="IXTYPID-c-g"></div></div> <div class="IXTYPID-r-d" id="shortener"> <div class="IXTYPID-r-f"><img src="~/Image/me.png" width="34" height="39" /></div> <div class="IXTYPID-r-c" id="internal_message"></div> <div><b>Kısaltmak istenen Url'i buraya kopyalayınız:</b></div> <div class="IXTYPID-r-a" id="shortener_container"> <input class="IXTYPID-x-a IXTYPID-b-a IXTYPID-d-b IXTYPID-r-b" type="text" id="shortenerInputText" tabindex="1"> <div class="IXTYPID-d-a IXTYPID-w-a IXTYPID-b-a IXTYPID-r-g" tabindex="1" id="shortenerSubmitButton" aria-labelledby="gwt-uid-11" role="button"><span class="IXTYPID-b-a IXTYPID-w-f"></span> <span class="IXTYPID-b-a IXTYPID-w-h" onclick="shortUrl()">URL Kısalt</span></div> <div class="IXTYPID-v-a g-recaptcha" data-sitekey="6LchOvkSAAAAABtPQPc0LH1A6rqU5WR9CXFssNJV"><div><div style="width: 304px; height: 78px;"><iframe frameborder="0" hspace="0" marginheight="0" marginwidth="0" scrolling="no" style="" tabindex="0" vspace="0" width="304" title="recaptcha widget'ı" role="presentation" height="78" id="I0_1438082275995" name="I0_1438082275995" src="https://www.google.com/recaptcha/api2/anchor?k=6LchOvkSAAAAABtPQPc0LH1A6rqU5WR9CXFssNJV&co=aHR0cHM6Ly9nb28uZ2w.&hl=tr&v=r20150722114659&size=normal&usegapi=1&jsh=m%3B%2F_%2Fscs%2Fapps-static%2F_%2Fjs%2Fk%3Doz.gapi.en.jqFfHqiz5j8.O%2Fm%3D__features__%2Fam%3DQQ%2Frt%3Dj%2Fd%3D1%2Ft%3Dzcms%2Frs%3DAGLTcCP7hMFJ5KmE915Yi8mDQmZIen1WYg#id=I0_1438082275995&parent=https%3A%2F%2Fgoo.gl&pfname=&rpctoken=60400975"></iframe></div><textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid #c1c1c1; margin: 10px 25px; padding: 0px; resize: none; display: none; "></textarea></div></div></div> <div>Tüm url kısaltmaları borakasmer.com'dan erişilebilir..</div> </div> <h2><b><span id="result" style="color:crimson;padding-left: 0.7cm"></span></b></h2> </div> </body> </html> |
Öncelikle [A-Z] ve [0-9] arasından random seçilecek 8 karakter nasıl oluşturulur onu inceleyelim.
Aşağıda GetRandomUrl() methodu belirtilen karakterler arasında Linq sayesinde “Enumerable.Repeat()” kullanarak random 8 karakter seçmektedir.
1 2 3 4 5 6 7 8 9 10 |
public string GetRandomUrl() { var chars = "abcdefghijklmnopqrstuvwxyz0123456789"; var random = new Random(); var result = new string( Enumerable.Repeat(chars, 8) .Select(s => s[random.Next(s.Length)]) .ToArray()); return result; } |
“ShortUrl()” methodu aşağıda görüldüğü gibi “GetRandomUrl()” methodu ile shortUrl üretilir. Eğer önceden böyle bir url üretilmiş ise “While()” döngüsü içinde unique bir url çekilene kadar işlem tekrarlanır. Daha sonra short url ve uzun olan gerçek url Database’e kaydedilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public string ShortUrl(string Url) { if (Url.Trim() != "") { string shortUrl = GetRandomUrl(); using (UrlContext dbContext = new UrlContext()) { while (dbContext.Urls.Any(ur => ur.ShortUrl == shortUrl)) { shortUrl = GetRandomUrl(); } Urls data = new Urls(); data.ShortUrl = shortUrl; data.Url = Url; dbContext.Urls.Add(data); dbContext.SaveChanges(); return shortUrl; } } return ""; } |
Şimdi sıra geldi girilen kısa Url’i istenen gerçek url’e yönlendirmesine:
Öncelikle RouteConfig.cs’e aşağıdaki “RedirectLink” yolu eklenir.
1 2 3 4 5 |
routes.MapRoute( name: "RedirectLink", url: "RedirectLink", defaults: new { controller = "Home", action = "RedirectLink" } ); |
Web.config dosyasına aşağıdaki “customErrors” tagı eklenir. Amaç örneğin “http://localhost:7461/xb84w3r8” şeklinde sayfaya gelindiğinde böyle bir route’a uyan kural olmadığı için hata sayfasına düşmesidir. Böylece RedirectLink action’ında gelen shortUrl’i “Request[“aspxerrorpath”]” parametresinden çekilerek alınır. Daha sonra bu shortUtl’e ait gerçek Url’i, Database’den çekilerek(301) permanent Redirect edilir ve sayfaya yönlendirilir. (301) redirect ile kalıcı bir aktarma yapılarak arama botlarının sayfa sayımında, gerçekte yönlendirilen sayfanın sayması sağlanır. Örnek olarak “http://localhost:7461/xb84w3r8” değil de gerçekte yönlendirilen “http://borakasmer.com” arama botlarınca sayfa gösterimi sayılmış olunur.
Web.config:
1 2 3 |
<customErrors mode="On" > <error statusCode="404" redirect="~/Home/RedirectLink" /> </customErrors> |
HomeController/RedirectLink:
1 2 3 4 5 6 7 8 9 |
public void RedirectLink() { using (UrlContext dbContext = new UrlContext()) { string url = Request["aspxerrorpath"]?.Replace("/", ""); string longUrl = dbContext.Urls.Where(u => u.ShortUrl == url).Select(s => s.Url).FirstOrDefault().ToString(); Response.RedirectPermanent(longUrl, true); } } |
Böylece geldik bir makalenin daha sonuna yeni bir makalede görüşmek üzere hoşçakalın.
Source:
- https://www.codeproject.com/Questions/990970/How-to-generate-the-more-than-random-alphanumeric
- https://stackoverflow.com/questions/15467037/how-to-display-requested-querystrings-along-with-aspxerrorpath
elinize sağlık .
Teşekkürler Çağrı.
can you please share work file please
Eline sağlık hocam, çok işimize yaradı. google kapatmış bu hizmetini, diğerleride ücretli oluyor çünkü biz bu mantığı sms atarken kullanacağımız için diğer firmalarda kısıtlama filan koymuş 1000 kısa link sonrası ücretli diye(üstelik 30$ ortlama aylık)
Teşekkürler Hamit,
İşine yaramasına çok sevindim. Ben de zamanında baya kullandım bunu :)
Hocam, uzun zamandır kullanıyoruz iş biraz büyüdü :) gelen istek sayıları artınca web servisde(asp.net mvc api) şöyle bir sorun çıkmaya başladı;
>web servise gelen istek saniyede 100-150 civarında. Bu isteği yapan bir windows servis.
>kayıtlar database üzerinde çiftlemeye başladı hatta aynı kayıtdan 3 tane bile atıyor. Bu senaryonun önüne nasıl geçebilirim. procedure yazdım içine kontroller ekledim nasıl oluyorsa üretilen kısa kod bile aynı oluyor. sanırım asenkron yapı ile ilgili bilmediğim kaçırdığım bir durum var. Hangi konuyu araştırmalıyım kaçırdığım nokte ne olabilir. Teşekkürler.
Ek bilgi > isteği yapan windows servis, her saniye datasında kayıt varmı diye kontrol edip varsa bu kayıtları URL kısaltma işlemi yaptığım api’ye yolluyor api cevap döndüğünde kayıtlarını güncelliyor. Api daha cevap veremeden servis sonraki saniye ye geçmiş oluyor ve yine istek yapıyor.
Burda bazı kayıtlar cevap alamadan tekrar ikinci saniyeye geçiyor. İşte burada bişeyler oluyor :D
Hamit kardeşim kısa url alanına unique index ekle,
Db ye yazan kısımda exeception kontrolü yap hata alırsan baştan oluştursun yani bu işlemi Db ye yazana kadar döndüren bir döngüde yapın…Db yazması ile loop dan çıksın…Boracım çok zaman oldu görüşelim…
Olur hocam. Gecenlerde seni andık :)