Kesin yazılmış MVC3 görünümünden modeli geçirmek için jquery'de AJAX Post'u kullanmanın doğru yolu


101

Acemi bir web programcısıyım, bu yüzden "jargonum" dan bazıları doğru değilse lütfen beni affedin. MVC3 çerçevesini kullanan ASP.NET kullanan bir projem var.

Yöneticinin bir ekipman listesini değiştireceği bir yönetici görünümü üzerinde çalışıyorum. İşlevlerden biri, MVC denetleyicisine bir gönderi gönderdikten sonra web sayfasındaki girişi dinamik olarak düzenlemek için jquery'yi kullanmak istediğim bir "güncelle" düğmesidir.

Bu yaklaşımın, web sayfasının veritabanıyla senkronizasyondan çıkmasıyla ilgili minimum endişenin olduğu tek bir yönetici ayarında "güvenli" olduğunu düşünüyorum.

Kesinlikle yazılmış bir görünüm oluşturdum ve model verilerini bir AJAX gönderisi kullanarak MVC kontrolüne geçirmeyi umuyorum.

Aşağıdaki gönderide , yapmakta olduğum şeye benzer bir şey buldum: JQuery Ajax ve ASP.NET MVC3 null parametrelere neden oluyor

Yukarıdaki gönderideki kod örneğini kullanacağım.

Model:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Denetleyici:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

Görünümde komut dosyası:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

Henüz yukarıdakileri kullanma şansım olmadı. Ancak model verilerini AJAX kullanarak MVC kontrolüne geri göndermenin "en iyi" yöntemi olup olmadığını merak ediyordum.

Model bilgilerini ifşa etmekten endişe duymalı mıyım?

Yanıtlar:


72

Var bildirimini ve stringify'ı atlayabilirsiniz. Aksi takdirde, bu gayet iyi çalışacaktır.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});

Küçük ayarlamayı gösterdiğin için teşekkürler. Model yapısını güvenlik açısından açığa çıkarmakla ilgili herhangi bir endişe var mı?
John Stone

Göze batan hiçbir şey benim için bir güvenlik sorunu olarak öne çıkmıyor. Bununla ilgili gerçekten endişeleniyorsanız, mvc tarafında her zaman özel bir model bağlayıcı yapabilirsiniz.
Craig M

8
Bu benim için başarısız oldu. Çağrının MVC5'te çalışması için JSON.stringify ({...}) kullanmam gerekiyordu.
Johncl

API denetleyicileriyle çalışırken de aynısını yapmam gerektiğini fark ettim. Bu cevap, API denetleyicileri var olmadan 4 yıl önce yazılmıştır.
Craig M

1
tanrım damit, contentType yerine dataType vardı, bu her zaman beni alır !!
Phil

175

Bunu uygulamanın 3 yolunu buldum:

C # sınıfı:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Aksiyon:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript bunu üç şekilde yapabilirsiniz:

1) Sorgu Dizesi:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

Buradaki veriler bir dizedir.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Nesne Dizisi:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

Buradaki veriler, anahtar / değer çiftlerinden oluşan bir dizidir:

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

Buradaki veriler, serileştirilmiş bir JSON dizesidir. Adın, sunucudaki parametre adıyla eşleşmesi gerektiğini unutmayın !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'

1
Henüz bilmediğim soruları çözen bu harika, kapsamlı cevapla karşılaştım. +1, teşekkürler!
SeanKilleen

# 2 aradığım şeydi. Cevap bu olmalı.
TheGeekZn

DÜZENLEME: data: $('input, textarea, select').serialize(),benimkinin çalışması için kullanmak zorunda kaldı .
TheGeekZn

Hey Jazaret !! 3. yaklaşımla modele tarih nasıl aktarılır?
Guruprasad Rao

1
Gecikme için özür dilerim @GuruprasadRao Bir tarihi geçmek için tarih ve saatin javascript kodunda bir dize olmasını sağlayabilirsiniz ve MVC bunu bir DateTime nesnesine çevirecektir.
Jazaret

12

Benim için bu şekilde çalıştı:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}

8

sahip olduğunuz şey sorun değil - ancak bir miktar yazmayı kaydetmek için, verileriniz için kullanabilirsiniz

veri: $ ('# formId']. serialize ()

bkz http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ ayrıntılar için, sözdizimi oldukça basit.


Seri hale getirme işlevini kullanmak için, sınıfın her üyesinin bir form nesnesinde kullanılması gerektiğini anlıyorum. Bu doğruysa, SOL olabilirim.
John Stone

1
ah ya .. yoksa serileştirmeyi kullanamazsın. Yine de her zaman DOM'u işleyebilir ve bu öğelerle bir form oluşturabilir ve onu serileştirebilirsiniz - ancak ... o zaman alanların manuel olarak yazılması muhtemelen daha temiz olacaktır.
Adam Tuliper - MSFT

@TahaRehmanSiddiqui gerçekten IE'de çalışıyor, ne işe yaramıyor? bir hata alıyor musun?
Adam Tuliper - MSFT

modelimin her özelliği boş çıkıyor
Taha Rehman Siddiqui

@TahaRehmanSiddiqui, form alanlarınızın 'adı' model özelliklerinizin adlarıyla eşleşiyor mu?
MongooseNX

0

MVC 5 kullanıyorsanız bu çözümü okuyun!

Sorunun özellikle MVC 3 için çağrıldığını biliyorum, ancak bu sayfaya MVC 5 ile rastladım ve durumumdaki herhangi biri için bir çözüm göndermek istedim. Yukarıdaki çözümleri denedim ama benim için işe yaramadı, Eylem Filtresine asla ulaşılmadı ve nedenini anlayamadım. Projemde sürüm 5 kullanıyorum ve aşağıdaki eylem filtresiyle son buldum:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

- Yap notu using System.Web.Mvcve using System.Web.Mvc.Filtersdeğil httpkütüphaneleri (O MVC v5 ile değişti şeylerden biri olduğunu düşünüyorum. -

Ardından, filtreyi [ValidateJSONAntiForgeryHeader]eyleminize (veya denetleyicinize) uygulayın ve doğru şekilde çağrılmalıdır.

Yukarıda sağda benim düzeni sayfasında </body>ben@AntiForgery.GetHtml();

Son olarak Razor sayfamda ajax çağrısını şu şekilde yapıyorum:

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});

1
Tüm form değerlerinizi manuel olarak mı alıyorsunuz? Neden olmasın data: $("#the-form").serialize()?
Sinjai

1
@Sinjai Koduma tekrar bakmam gerekecek, ancak orada başka işlemler de yaptığıma inanıyorum. ".serialize ()", yalnızca giriş değerlerine ihtiyacınız olduğunda da işe yarar
blubberbo

Endişelenme, sadece merak ettim.
Sinjai
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.