29

I'm trying to learn asp.net and so far I can load other page contents without refreshing using Ajax.Actionlink and AjaxOptions() but I can't figure it out how to use ajax when submitting a form. I did a lot of googling but couldn't find the appropriate solution. Here are my codes,

Controller page

namespace CrudMvc.Controllers
{
public class HomeController : Controller
{
    sampleDBEntities db = new sampleDBEntities(); 
    //
    // GET: /Home/

    public ActionResult Index()
    {
        return View(db.myTables.ToList());
    }

    public PartialViewResult Details(int id = 0)
    {
        myTable Table = db.myTables.Find(id);
        return PartialView(Table);
    }

    [HttpGet]
    public PartialViewResult Create()
    {
        return PartialView();
    }

    [HttpPost]
    public ActionResult Create(myTable table)
    {
        if (ModelState.IsValid)
        {
            db.myTables.Add(table);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(table);
    }

    protected override void Dispose(bool disposing)
    {
        db.Dispose();
        base.Dispose(disposing);
    }
}
}

Index View page

@model IEnumerable<CrudMvc.Models.myTable>

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>

<h2>Index</h2>

<p>
@Ajax.ActionLink("Add New", "Create", new AjaxOptions()
   {
    HttpMethod = "GET",
    UpdateTargetId = "info",
    InsertionMode = InsertionMode.Replace   
   })
</p>
<div id="main">
<table>
<tr>
    <th>
        @Html.DisplayNameFor(model => model.name)
    </th>
    <th>Action</th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.name)
    </td>
    <td>
        @Ajax.ActionLink("Details", "Details", new{ id=item.id}, new AjaxOptions()
   {
    HttpMethod = "GET",
    UpdateTargetId = "info",
    InsertionMode = InsertionMode.Replace   
   })
    </td>
</tr>
}
</table>
</div>
<div id="info"></div>

Create View Page

@model CrudMvc.Models.myTable

@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>myTable</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.id)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.id)
        @Html.ValidationMessageFor(model => model.id)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.name)
        @Html.ValidationMessageFor(model => model.name)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

<script>
var form = $('#main');
$.ajax({
    cache: false,
    async: true,
    type: "POST",
    url: form.attr('action'),
    data: form.serialize(),
    success: function (data) {
        alert(data);
    }
});
</script>

<div>
@Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
Shihan Khan
  • 2,180
  • 4
  • 34
  • 67
  • 1
    Some articles showing use of `Html.BeginForm()` [Html.BeginForm() vs Ajax.BeginForm() in MVC3](http://www.codeproject.com/Articles/429164/Html-BeginForm-vs-Ajax-BeginForm-in-MVC) and [Using Ajax.BeginForm() with ASP.NET MVC](http://www.blackbeltcoder.com/Articles/script/using-ajax-beginform-with-asp-net-mvc) –  Oct 04 '14 at 10:20

1 Answers1

78

Here goes the complete example -

Lets create a simple model -

public class Details
{
    public string Name { get; set; }
    public string Email { get; set; }
}

Now lets create couple of Actions to make GET and POST requests using AJAX BEGINFORM -

    static List<Details> details = new List<Details>(); 
    public ActionResult GetMe()
    {
        return View();
    }

    public ActionResult SaveData(Details d)
    {
        details.Add(d);
        return Json(details.Count, JsonRequestBehavior.AllowGet);
    }

Then lets create a simple view which will host Ajax.BeginForm() -

@model RamiSamples.Controllers.Details

@{
    ViewBag.Title = "Ajax";
}

<h2>Ajax</h2>
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>

@using (Ajax.BeginForm("SaveData", new AjaxOptions()
{
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "dane"
}))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Details</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            @Html.ValidationMessageFor(model => model.Email)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div id="dane">
    Number of Details : 
</div>

Now when the page gets rendered -

enter image description here

Now when you enter data and click on create button -

enter image description here

And then the page will automatically updated with the number of additions as shown below -

enter image description here

ramiramilu
  • 17,044
  • 6
  • 49
  • 66
  • @ramiramilu Thanks for this nice example. I have managed to apply this approach, but encountered 2 problems: 1) I used to return `TempData["message"]` from Controller to View. Actually it seems to be filled and returned to the View, but cannot be seen. Is it possible to use `TempData["message"]` with this approach? 2) I cannot pass the uploaded file `IEnumerable files` to the Controller with this approach. how to resolve this? – Jack Jun 16 '15 at 10:45
  • @Christof You can upload files using AJAX and I once way I can think of to use `TempData` would be to return a `PartialView` and update the targeted div. – ramiramilu Jun 16 '15 at 12:04
  • @ramiramilu Could you give an example please by adding an update to your answer? – Jack Jun 16 '15 at 12:33
  • 2
    @Christof to protect the integrity of the answer, I would suggest to post a new question with specific details. – ramiramilu Jun 16 '15 at 12:47
  • @ramiramilu You are right. I opened a new question, could you please have a look at [this](http://stackoverflow.com/questions/30868493/form-reload-but-partialview-cannot-with-ajax-in-mvc) question? – Jack Jun 16 '15 at 13:08
  • @ramiramilu Any idea? – Jack Jun 16 '15 at 13:21
  • I found this while trying to work out how to do a similar thing - when I implement a variation of the above, the result is shown on a new blank page - I'm guessing the request is firing as a standard post rather than via ajax - any ideas why this might happen? – Wayne Feltham Aug 27 '15 at 11:46
  • @WayneFeltham, have you referenced the ajax js scripts? – ramiramilu Aug 28 '15 at 06:56
  • 1
    Hi, I got it working - it was because I needed various references - not sure why...here's what I've ended up with that works... bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js")); bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( "~/Scripts/jquery.validate*", "~/Scripts/jquery.unobtrusive*")); – Wayne Feltham Aug 30 '15 at 15:34
  • is there anyway to specify the model per form> instead of per page? Say I wanted 2 AJAX forms on a page, each with different models. – Zapnologica May 22 '16 at 11:13
  • why `.Count()` is not always 1 ? Where is `List
    details` stored?
    – Muflix Mar 09 '18 at 10:50