ASP.NET MVC tindakan pengontrol yang mengembalikan JSON atau sebagian html

406

Saya mencoba membuat tindakan pengontrol yang akan mengembalikan JSON atau sebagian html tergantung pada parameter. Apa cara terbaik untuk mengembalikan hasilnya ke halaman MVC secara tidak sinkron?

NathanD
sumber

Jawaban:

519

Dalam metode tindakan Anda, kembalikan Json (objek) untuk mengembalikan JSON ke halaman Anda.

public ActionResult SomeActionMethod() {
  return Json(new {foo="bar", baz="Blech"});
}

Kemudian panggil saja metode tindakan menggunakan Ajax. Anda bisa menggunakan salah satu metode pembantu dari ViewPage seperti

<%= Ajax.ActionLink("SomeActionMethod", new AjaxOptions {OnSuccess="somemethod"}) %>

SomeMethod akan menjadi metode javascript yang kemudian mengevaluasi objek Json yang dikembalikan.

Jika Anda ingin mengembalikan string biasa, Anda bisa menggunakan ContentResult:

public ActionResult SomeActionMethod() {
    return Content("hello world!");
}

ContentResult secara default mengembalikan teks / polos sebagai contentType.
Ini kelebihan beban sehingga Anda juga dapat melakukan:

return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
Haacked
sumber
9
maaf phil! ini tidak benar-benar menjawab pertanyaan, bukan? itu benar-benar berguna tetapi sebagai brad mengatakan Anda perlu mencari tahu apa yang mereka minta dan mengembalikan hasilnya sesuai.
Simon_Weaver,
lihat pertanyaan saya yang agak terkait (baik yang membawa saya ke sini) di stackoverflow.com/questions/482363/…
Simon_Weaver
9
jika Anda menemukan jawaban, tautkan dalam pertanyaan itu sendiri. Juga saya tidak berpikir memeriksa ini karena jawabannya adalah hal yang benar.
Cherian
Apa nama yang sepenuhnya memenuhi syarat kelas Json itu?
Josh Withee
112

Saya pikir Anda harus mempertimbangkan AcceptTypes dari permintaan. Saya menggunakannya dalam proyek saya saat ini untuk mengembalikan jenis konten yang benar sebagai berikut.

Tindakan Anda pada pengontrol dapat mengujinya seperti pada objek permintaan

if (Request.AcceptTypes.Contains("text/html")) {
   return View();
}
else if (Request.AcceptTypes.Contains("application/json"))
{
   return Json( new { id=1, value="new" } );
}
else if (Request.AcceptTypes.Contains("application/xml") || 
         Request.AcceptTypes.Contains("text/xml"))
{
   //
}

Anda kemudian dapat menerapkan aspx view untuk memenuhi sebagian kasus respons xhtml.

Kemudian di jQuery Anda bisa mengambilnya lewat parameter tipe sebagai json:

$.get(url, null, function(data, textStatus) {
        console.log('got %o with status %s', data, textStatus);
        }, "json"); // or xml, html, script, json, jsonp or text

Semoga ini bisa membantu James

James Green
sumber
5
Terima kasih James, itu bisa sangat berguna untuk membuat semacam situs web dan API REST menggunakan Tindakan Kontrol yang sama.
NathanD
Jika saya memiliki banyak metode seperti ini di controller saya, adakah cara yang bisa saya lakukan ini secara lebih umum?
Seph
Di mana namespace adalah kelas Json? Apa ketergantungan untuk project.json? Terima kasih sebelumnya
Andrei
1
Itulah kelas JsonResult dari System.Web.Mvc (dalam System.Web.Mvc.dll) @Andrei
James Green
Terima kasih, sudah menemukannya. Mungkin memperbarui jawaban untuk mencerminkan API baru? Btw, saya menggunakan inti dotnet di mana itu Microsoft.AspNetCore.Mvc.JsonResult.
Andrei
78

Cara lain yang bagus untuk menangani data JSON adalah menggunakan fungsi getJSON JQuery. Anda dapat menghubungi

public ActionResult SomeActionMethod(int id) 
{ 
    return Json(new {foo="bar", baz="Blech"});
}

Metode dari metode getJSON jquery hanya dengan ...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);
Pengembang SaaS
sumber
15
Ini sama sekali tidak menjawab pertanyaan.
Aaronaught
2
@Aonaonaught Sebenarnya bagian pertama return Json(new {foo="bar", baz="Blech"});!
SparK
Juga pertimbangkan $ .post stackoverflow.com/questions/751218/… (ASP.Net MVC default untuk menonaktifkan JSON Dapatkan permintaan untuk alasan keamanan)
Greg
50

Saya menemukan beberapa masalah mengimplementasikan panggilan MVC ajax GET dengan JQuery yang membuat saya sakit kepala sehingga berbagi solusi di sini.

  1. Pastikan untuk memasukkan tipe data "json" dalam panggilan ajax. Ini akan secara otomatis menguraikan objek JSON yang dikembalikan untuk Anda (mengingat server mengembalikan json yang valid).
  2. Termasuk JsonRequestBehavior.AllowGet; tanpa MVC ini mengembalikan kesalahan HTTP 500 (dengan dataType: jsonditentukan pada klien).
  3. Tambahkan cache: falseke panggilan $ .ajax, jika tidak, Anda pada akhirnya akan mendapatkan tanggapan HTTP 304 (alih-alih tanggapan HTTP 200) dan server tidak akan memproses permintaan Anda.
  4. Akhirnya, json adalah case-sensitive, sehingga casing dari elemen-elemen tersebut harus cocok di sisi server dan sisi klien.

Contoh JQuery:

$.ajax({
  type: 'get',
  dataType: 'json',
  cache: false,
  url: '/MyController/MyMethod',
  data: { keyid: 1, newval: 10 },
  success: function (response, textStatus, jqXHR) {
    alert(parseInt(response.oldval) + ' changed to ' + newval);                                    
  },
  error: function(jqXHR, textStatus, errorThrown) {
    alert('Error - ' + errorThrown);
  }
});

Contoh kode MVC:

[HttpGet]
public ActionResult MyMethod(int keyid, int newval)
{
  var oldval = 0;

  using (var db = new MyContext())
  {
    var dbRecord = db.MyTable.Where(t => t.keyid == keyid).FirstOrDefault();

    if (dbRecord != null)
    {
      oldval = dbRecord.TheValue;
      dbRecord.TheValue = newval;
      db.SaveChanges();
    }
  }

    return Json(new { success = true, oldval = oldval},
                JsonRequestBehavior.AllowGet);
}
Shane
sumber
13

Untuk menjawab bagian lain dari pertanyaan, Anda dapat menghubungi:

return PartialView("viewname");

ketika Anda ingin mengembalikan sebagian HTML. Anda hanya perlu menemukan beberapa cara untuk memutuskan apakah permintaan tersebut menginginkan JSON atau HTML, mungkin berdasarkan bagian / parameter URL.

Brad Wilson
sumber
2
jadi bukankah pertanyaannya tetap tidak terjawab?
Simon_Weaver
2
Ini tidak menjawab pertanyaan.
Aaronaught
dia sedang mencari permintaan ajax untuk mendapatkan html menggunakan PartialView membutuhkan refresh halaman kecuali Anda mengembalikan tampilan dari metode tindakan menggunakan panggilan ajax
Chris McGrath
7

Solusi alternatif dengan kerangka kerja pengkodean

Aksi kembalinya json

Pengendali

    [HttpGet]
    public ActionResult SomeActionMethod()
    {
        return IncJson(new SomeVm(){Id = 1,Name ="Inc"});
    }

Halaman silet

@using (var template = Html.Incoding().ScriptTemplate<SomeVm>("tmplId"))
{
    using (var each = template.ForEach())
    {
        <span> Id: @each.For(r=>r.Id) Name: @each.For(r=>r.Name)</span>
    }
}

@(Html.When(JqueryBind.InitIncoding)
  .Do()
  .AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
  .OnSuccess(dsl => dsl.Self().Core()
                              .Insert
                              .WithTemplate(Selector.Jquery.Id("tmplId"))
                              .Html())
  .AsHtmlAttributes()
  .ToDiv())

Aksi pengembalian html

Pengendali

    [HttpGet]
    public ActionResult SomeActionMethod()
    {
        return IncView();
    }

Halaman silet

@(Html.When(JqueryBind.InitIncoding)
  .Do()
  .AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
  .OnSuccess(dsl => dsl.Self().Core().Insert.Html())
  .AsHtmlAttributes()
  .ToDiv())
Vlad
sumber
4

PartialViewResult dan JSONReuslt mewarisi dari kelas dasar ActionResult. jadi jika tipe pengembalian diputuskan secara dinamis mendeklarasikan output metode sebagai ActionResult.

public ActionResult DynamicReturnType(string parameter)
        {
            if (parameter == "JSON")
                return Json("<JSON>", JsonRequestBehavior.AllowGet);
            else if (parameter == "PartialView")
                return PartialView("<ViewName>");
            else
                return null;


        }
Anil Vaddepally
sumber
3

Untuk orang-orang yang telah mengupgrade ke MVC 3 di sini adalah cara yang rapi Menggunakan MVC3 dan Json

Sarath
sumber
1
Anda juga dapat menggunakan teknik yang sama seperti artikel ini di MVC 2
longhairedsi
2
    public ActionResult GetExcelColumn()
    {            
            List<string> lstAppendColumn = new List<string>();
            lstAppendColumn.Add("First");
            lstAppendColumn.Add("Second");
            lstAppendColumn.Add("Third");
  return Json(new { lstAppendColumn = lstAppendColumn,  Status = "Success" }, JsonRequestBehavior.AllowGet);
            }
        }
sakthi
sumber
dapatkah Anda menambahkan sedikit informasi tentang apa yang dilakukannya?
RealCheeseLord
Karena kode Anda menunjukkan itu kembali JSON, jenis kembali harus JsonResult dan bukan ActionResult
noobprogrammer
0

Pendekatan fleksibel untuk menghasilkan output yang berbeda berdasarkan permintaan

public class AuctionsController : Controller
{
  public ActionResult Auction(long id)
  {
    var db = new DataContext();
    var auction = db.Auctions.Find(id);

    // Respond to AJAX requests
    if (Request.IsAjaxRequest())
      return PartialView("Auction", auction);

    // Respond to JSON requests
    if (Request.IsJsonRequest())
      return Json(auction);

    // Default to a "normal" view with layout
    return View("Auction", auction);
  }
}

The Request.IsAjaxRequest()Metode ini cukup sederhana: itu hanya memeriksa HTTP header untuk permintaan yang masuk untuk melihat apakah nilai X Diminta--Dengan header XMLHttpRequest, yang secara otomatis ditambahkan oleh sebagian besar browser dan kerangka AJAX.

Metode ekstensi khusus untuk memeriksa apakah permintaan untuk json atau tidak sehingga kami dapat memanggilnya dari mana saja, seperti metode ekstensi Request.IsAjaxRequest ():

using System;
using System.Web;

public static class JsonRequestExtensions
{
  public static bool IsJsonRequest(this HttpRequestBase request)
  {
    return string.Equals(request["format"], "json");
  }
}

Sumber: https://www.safaribooksonline.com/library/view/programming-aspnet-mvc/9781449321932/ch06.html#_javascript_rendering

Mannan Bahelim
sumber