Postal ile e-posta gönderme

Önceleri uygulama içinde dinamik yani içeriği çalışma zamanı değişkenlik gösteren  e-­posta gönderileri için ;

App_Data klasörünün altına şablonlartemplate oluşturup, değişken alanlarını küme parantezler ile belirliyor

daha sonra ise biçimlendirip gönderiyordum.

Şimdilerde ise Postal kullanıyorum.

Kullandığınız sürüme göre paketi kuruyoruz.

Kurulum sonrası View klasörünün altına “Emails” adından yeni bir klasör oluşuyor. Bundan sonra şablonlarımızı bunun altında cshtml uzantılı olarak ekliyoruz. Parametreleri de ViewBag ile belirtiyoruz.

Son olarak controller de gönderiyoruz.

Daha detaylı bilgi için ürünün sayfasına bakabilirsiniz..

Bootsrap Panel Helper

Kullanım şekli;

@using (Html.Panel("Genel", type: PanelType.success))
{
    @Html.Editor(model => Model.Error)
    @Html.Editor(model => Model.SaltKey)
}

Panel in tipleri için enum;

public enum PanelType
{
    @default,
    success,
    info,
    danger
}

Panel i containerkap gibi kullanabilmek için ViewContext ve kapanış etiketleritag için de IDisposable dan faydalanıyoruz.

public class PanelFieldSet : IDisposable
{
    bool _disposed;
    readonly ViewContext _viewContext;
    readonly TextWriter _writer;

    public PanelFieldSet(ViewContext viewContext)
    {
        if (viewContext == null)
            throw new ArgumentNullException("viewContext");
        _viewContext = viewContext;
        _writer = viewContext.Writer;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _disposed = true;
            _writer.Write("\t\t</div>\r\n\t</div>\r\n");
        }
    }

    public void EndDiv()
    {
        Dispose(true);
    }
}

Son olarak Html Helper a yatalık yapacak ControlHelper sınıfıclass;

public static class ControlHelper
{
    public static PanelFieldSet Panel(this HtmlHelper htmlHelper, string title, PanelType type = PanelType.@default, bool display = true, int bodyHeight = 0)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("<div class=\"panel panel-{0}\" class='{1}'>", Enum.GetName(typeof(PanelType), type), display ? "show" : "hide");
        sb.AppendFormat("<div class=\"panel-heading\">{0}</div>", title);
        sb.AppendFormat("<div class=\"panel-body\" {0}>", bodyHeight == 0 ? "" : string.Format("style='height:{0}px'", bodyHeight));
        htmlHelper.ViewContext.Writer.WriteLine(sb.ToString());
        return new PanelFieldSet(htmlHelper.ViewContext);
    }
}

JQueryUI Modal İle Mvc AJax Loader

Web uygulamalarında asenkronAsynchronous işlemler yapılırken kullanıcıya durum boyunca bilgi vermenin 500 farklı yolu mutlaka vardır. Lakin en temiz olanı, tüm ekranı kapatıp tam ortada bildirimi yapmakmış gibi gözüküyor. Bunun en büyük avantajı “istenmeyen tıklamalar” dan korunmak olarak izah edebilir.

Bunun için JQueryUI elemanWidget larından Dialog‘u kullanacağız. Hali hazırda MVC Proje Template içinde bulunduğu için işimiz gayet kolay olacak.

Queryui solution explorer

_Layout ile başlayalım;

Head içine sırası ile css ve js dosyalarını ekleyelim.

<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.18.min.js")" type="text/javascript"></script>

Dialog açıldığında kullanıcı tarafından kapatılmasını engellemek için sağ üst köşedeki “x” kapatı işaretini kaldıralım.

<style type="text/css">
.ui-dialog-titlebar-close {
    display: none;
}
</style>

Dialog için kullanılacak div tanımını yapalım.

<div id="dialog-modal" title="Bilgilendirme">
    <p>
        <img src="/Content/images/loading.gif.jpgx" style="vertical-align: middle;" />
        işlem yapılıyor ...
    </p>
</div>

Div’ i Dialog haline getirelim.

<script type="text/javascript">
    $(function () {
        $("#dialog-modal").dialog({
            autoOpen: false,
            modal: true,
            height: 100,
            closeOnEscape: false,
            draggable: false,
            resizable: false
        });
    });
</script>

Son olarak, çağrıda bulunacak alt sayfaların da kendi script bloklarını yazacakları Section‘ı tanımlayalım.

@RenderSection("script", false)

Alt sayfalardaki script alanına iki adet fonksiyonfunction ekliyoruz. Asenkron işlem başladığında ve bittiğinde Dailog açılacak ve kapanacak.

<script type="text/javascript">
    function start() {
        $("#dialog-modal").dialog('open');
    }
    function finish() {
        $("#dialog-modal").dialog('close');
    }
</script>

AjaxOptions sınıfclass ını da tanımlarsak işlem tamamlanmış olacak.

@using (Ajax.BeginForm("Index", "Home", new AjaxOptions
{
    HttpMethod = "post",
    OnBegin = "start",
    OnSuccess = "finish"
}))

Loading gif

Mvc İle Asenkron İşlem Yapmak

Mvc uygulamalarında AsenkronAsynchronous işlem yapmak için ya Jquery yada Ajax Helper kullanmak gerekir (genelde). Jquery ile ilgili kaynak bulmak kolay iken Ajax Helper için pek de kolay değil. O yüzden bugün biraz araştırma yapma gereği hissettim.

Burada karşımıza iki adet metodçıkıyor;

  1. Ajax.ActionLink
  2. Ajax.BeginForm

Yaptıkları farklı olasada çalışma prensipleri aynı diyebilirim. Çünkü burada esas oğlan AjaxOptions sınıfı 🙂

BeginForm için basit bir örnek yapalım ve daha sonrasında ActionLink ile detaylara bakalım.

Ortak kullanım için bir sınıfclass oluşturalım;

[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Formu post edeceğimiz Action Method;

[HttpPost]
public string Create(Product product)
{
    //olaylar olaylar
    return "Ürün eklendi.";
}

Son olarak View formu oluşturalım;

@*Asenkron çalışması için gerekli script dosyaları*@
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
@using (Ajax.BeginForm("Create",//Controller deki metot adı
 new AjaxOptions
 {
    //form method
    HttpMethod = "post",
    //sonuç önceki ile yer değişiyor
    InsertionMode = InsertionMode.Replace,
    //işlem süresince çalışacak element id
    LoadingElementId = "loader",
    //işlem sonucunun gösterileceği element id
    UpdateTargetId = "result"
 }))
{
    <fieldset>
    <legend>Ürün</legend>
    @*Asenkron işlem sırasında kullanıcıya bilgi vermek için*@
    <div id="loader" style="display: none;">İşlem yapılıyor...</div>
    <div class="editor-label">
    Ad
    </div>
    <div class="editor-field">
    <input type="text" name="Name" />
    </div>
    <div class="editor-label">
    Fiyat
    </div>
    <div class="editor-field">
    <input type="text" name="Price" />
    </div>
    <p>
    <input type="submit" value="Ekle" />
    </p>
    @*İşlem sonucunda kullanıcıya bilgi vermek için*@
    <div id="result" style="color: maroon;"></div>
    </fieldset>
}

Peki sunucuserverdan gelecek olan veri daha karmaşık olursa ne yapacağız. Örneğin JSON formatında Product sınıfını döndürmek isteyebiliriz. İşe bu gibi durumlarda AjaxOptions unaşağıdaki özellikleriProperty ni kullanmak gerekir.

Çalışma sırasına göre;

  1. OnBegin(xhr, context)
  2. OnSuccess(result, status, xhr)
  3. OnComplete(xhr, status)
  4. OnFailure(xhr, status, error) (tabi hata olursa)

Yeni bir Action Method ekleyelim;

[HttpPost]
public JsonResult GetProduct(int Id)
{
    return Json(new Product
    {
        Id = Id,
        Name = string.Concat("Ürün ", Id),
        Price = Id * 12
    });
}

Çağrıda bulunmak için de Ajax.ActionLink kullanalım;

@Ajax.ActionLink("Ürün Detay",
"GetProduct",
new { Id = 1 },
    new AjaxOptions
    {
        HttpMethod = "post",
        OnComplete = "complete",
        OnFailure = "fail",
        OnBegin = "begin",
        OnSuccess = "success"
    })
<script type="text/javascript">
    function begin(xhr, content) {
        //olaylar
    }
    function success(result, status, xhr) {
        //olaylar
    }
    function complete(xhr, status) {
        //olaylar
    }
    function fail(xhr, status, error) {
        //olaylar
    }
</script>

İşlembaşarılı olduğunda sırası ile begin -> success -> complete fonksiyonları çalışır. Sonuçlar ise;

result
Result

status
status

xhr
xhr

Başarısız olduğunda ise begin -> fail fonksiyonları çalışır. Sonuçlar ise;

xhr
xhr

status
status

error
error

ReCaptcha Kullanımı

Bir Google servisi olan ReCaptcha. Bu yazıda lafı çok dolandırmadan hızlı bir şekilde Asp.Net Mvc uygulaması içinde Server SideSunucu Taraflı ReCaptcha kullanımını anlatacağım.

Edinme

Önce şu adresten kayıt olmalısınız. Bunun için uygulama geliştireceğiniz domain adını kaydetmeniz gerekmektedir. Test için mutlaka localhost u da eklemeyi unutmayın. İşlem sonundan iki adet Api Key oluşacak. Bir yere not edin 🙂

Daha sonra bu adresten .Net Library dosyasını indirin ve projenize referans olarak ekleyin.

Güncel JQuery dosyasını ilgili sayfalara referans vermeyi unutmayın.

Uygulama

ContactViewModel adında bir adet sınıfclass oluşturalım. Form içindeki verilerin Contoller de ki ilgili metoda post edilmesini bu sınıf yardımı ile yapacağız. Attribute ler yardımı ile de doğrulama işlemlerini de yaptırmış olacağız.

Yukarıda oluşturduğumuz sınıfı model olarak kullanabilecek bir Form oluşturacağız. Öncelikle API için gerekli anahtarları eşitleyelim.

Controller

Asenkron form işlemleri hakkında daha detaylı bilgi almak için şu yazıya göz atabilirsiniz.