Edits in List not being saved when partial view loaded MVC - ajax

I'm new to MVC. I have a view which displays the products attached to a Quote (the QuoteDetails). I also have an Ajax.ActionLink)_ for "Add product" which loads a partial view for another product to be entered. The problem is that when the partial view is loaded, edits to the other products not in the partial view are not saved. If no partial view is loaded, edits to the listed products are saved just fine.
Here is the relevant code for the main view:
#model CMSUsersAndRoles.Models.QuoteViewModel
....
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery.mask.min.js"></script>
#using (Html.BeginForm())
{
....
#Html.HiddenFor(model => model.CustomerId)
#Html.LabelFor(model => model.QuoteId)
#Html.EditorFor(model => model.QuoteId, new { htmlAttributes = new { #readonly = "readonly", #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuoteId)
.... // more controls for properties of Quote
#Html.LabelFor(model => model.QuoteDetail)
<div id="QuoteDetails">
#for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
#Html.HiddenFor(model => model.QuoteDetail[i].QuoteId, new { htmlAttributes = new { #class = "form-control" } })
....
#Html.EditorFor(model => model.QuoteDetail[i].SKU, new { htmlAttributes = new { #readonly = "readonly", #id = "SKU", #class = "form-control", style = "width: 100px" } })
#Html.EditorFor(model => model.QuoteDetail[i].Amount, new { htmlAttributes = new { #class = "form-control amount", style = "width: 95px" } })
#Html.ValidationMessageFor(model => model.QuoteDetail[i].Amount)
.... // more for controls for properties of QuoteDetail
#Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteDetail[i].QuoteId, quoteDetailId = (Model.QuoteDetail[i].QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.QuoteDetail[i].ProductName,
}, new { #class = "btn btn-danger glyphicon glyphicon-trash" })
</div>
}
#Html.EditorFor(model => model.Subtotal, new { htmlAttributes = new { #class = "form-control subTotal", style = "width: 100px; float:right; clear:left; text-align:right" } })
#Ajax.ActionLink("Add product", "AddProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetail.Count + 1) },
new AjaxOptions
{
UpdateTargetId = "QuoteDetails",
InsertionMode = InsertionMode.InsertAfter
})
}
Here is the partial view:
#model CMSUsersAndRoles.Models.QuoteDetail
#{
ViewBag.Title = "EditQuoteDetail";
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="row" class="row">
<table>
#using (Html.BeginCollectionItem("quoteDetail"))
{
<tr>
#Html.HiddenFor(model => model.QuoteId, new { htmlAttributes = new { #class = "form-control" } })
#Html.EditorFor(model => model.SKU, new { htmlAttributes = new { #readonly = "readonly", #id = "SKU", #class = "form-control", style = "width: 100px" } })
#Html.DropDownListFor(model => model.ProductId, new SelectList(ViewBag.ProductData, "ProductId", "Name"), "---Select one---", new { style = "width: 300px !important", htmlAttributes = new { #id = "ProductName", #class = "ProductList" } });
.... // more controls for properties of QuoteDetail
#Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.ProductName,
}, new { #class = "btn btn-danger glyphicon glyphicon-trash" })
</tr>
}
</table>
</div>
And here is the controller action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(QuoteViewModel qvm,
[Bind(Include = "CustomerId,SalesRep,FirstName,LastName,Company,Address1,Address2,City,State,PostalCode,WorkPhone,CellPhone,Email,Discount,PaymentTerms")] Customer customer,
[Bind(Include = "QuoteId,QuoteDetailId,ProductId,ProductName,Amount,ListPrice,Discount,Price")] List<QuoteDetail> quoteDetails,
[Bind(Include = "QuoteId,CustomerId,Subtotal,Tax,Total,QuoteDate,GoodUntil,QuoteSent,DateApproved,DateOrdered")] Quote quote)
{
....
}
Can anyone help with this? Any help will be much appreciated.

Your using 2 different techniques here to generate your collection which is causing the issue.
In the main view you have a for loop to generate controls for existing items which is generating the zero-based consecutive indexers, which is what the DefaultModelBinder uses by default. Your html will include name attributes that are for example
<input name="QuoteDetail[0].QuoteId"..../>
<input name="QuoteDetail[1].QuoteId"..../>
<input name="QuoteDetail[2].QuoteId"..../>
But then you add new items using the BeginCollectionItem helper method which generates the collection indexer as a Guid so that new inputs will be (where xxx is a Guid)
<input name="QuoteDetail[xxxx].QuoteId"..../>
and also includes a
<input name="QuoteDetail.Index" value="xxxx" ... />
which is used by the DefaultModelBinder to match non zero-based non consecutive indexers. You cannot use both techniques.
To solve this, you can either add an input for the indexer in the for loop
#for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
....
<input type="hidden" name="QuoteDetail.Index" value="#i" />
}
or change the loop to use the partial view containing the BeginCollectionItem method in each iteration
#foreach(var item in Model.QuoteDetail)
{
#Html.Partial("xxxx", item) // replace xxxx with the name of your partial
}

Related

how to save items of cascading drop down list in database with asp.net mvc

My Drop-Downs works well the problem is when I want to save my form.
here is my controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,TourId,StartDate,EndDate")] TourDate tourDate)
{
if (ModelState.IsValid)
{
db.TourDates.Add(tourDate);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
ViewBag.TourId = new SelectList(db.Tours, "Id", "TourName", tourDate.TourId);
return RedirectToAction("Index", "test");
}
[HttpPost]
public JsonResult GetT(int? id)
{
var tours = db.Tours.Where(e => e.CountryId == id).ToList()
.Select(e => new
{
Id = e.Id,
TourName= e.TourName
}).ToList();
return Json(tours);
}
and here is My form. in this From, selecttag with id=TourId is filling with data in ajax from the outer drop down dropdownId and it works fine
#Html.DropDownList("dropdownId",
Model.Countries.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.CountryName
}),
new { #class = "form-control" })
#using (Html.BeginForm("Create", "test"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TourDate</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.TourDate.TourId, "TourId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<select class="form-control" id="TourId"></select>
#Html.ValidationMessageFor(model => model.TourDate.TourId, "", new { #class = "text-danger" })
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.TourDate.StartDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TourDate.StartDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TourDate.StartDate, "", new { #class = "text-danger" })
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.TourDate.EndDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TourDate.EndDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TourDate.EndDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
the problem is when I submit the form no diffrent which Tour is chosen always there is TourId=0.
Appreciate any help and also here is the ajax if needed
$("#dropdownId").change(function () {
$('#TourId').empty();
var countrySelected = $(this).val();
$.ajax
({
url: '/test/GetT/' + countrySelected,
type: 'POST',
data: {
'countryId': countrySelected
},
success: function (data)
{
var $select = $('#TourId');
for (var i = 0; i < data.length; i++)
{
$('<option/>').attr('value', data[i].Id).html(data[i].TourName).appendTo('#TourId');
}
}
});
});
The reason your second <select> element does not submit a value is because it does not have a name attribute. It would need to be
<select class="form-control" name="TourDate.TourId" id="TourId"></select>
However there are multiple other errors and problems with your code. To note just a couple of them:
The model in your view is is not typeof TourDate (its a model
containing a property which is TourDate) so none of your controls
can be bound to your TourDate tourDate parameter in the POST
method (the model in the parameter needs to be the same as the model
in the view, or you need to use the [Bind(Prefix = "TourDate")]
attribute and you also need to remove the [Bind(Include = "..")]
attribute).
Your not getting client side validation associated with your
dropdownlists and in the POST method, if ModelState is invalid,
your just redirecting (the user would just assume the object has
been saved and not understand what is going on). You need to return
the view so errors can be corrected, but in your case, the values
the user has entered will be reset to the defaults (an annoying user
experience).
Your editing data, so you should always use a view model and in the controller method you need to populate the SelectList's to account for initial values and edited values (for when you need to return the view). You code should be
public class TourDateVM
{
[Required(ErrorMessage = "Please select a country")]
[Display(Name = "Country")]
public int? SelectedCountry { get; set; }
[Required(ErrorMessage = "Please select a tour")]
[Display(Name = "Country")]
public int? SelectedTour { get; set; }
[Required(ErrorMessage = "Please enter a start date")]
[Display(Name = "Start date")]
public DateTime? StartDate { get; set; }
.... // ditto above for EndDate
public IEnumerable<SelectListItem> CountryList { get; set; }
public IEnumerable<SelectListItem> TourList { get; set; }
}
And in the controller
public ActionResult Create()
{
TourDateVM model = new TourDateVM();
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult Create(TourDateVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
TourDate tour = new TourDate()
{
TourId = model.SelectedTour,
StartDate = model.StartDate,
EndDate= model.EndDate
};
db.TourDates.Add(tour);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
private ConfigureViewModel(TourDateVM model)
{
var counties = db.Countries;
model.CountryList = new SelectList(counties, "ID", "Name"); // adjust to suit your property names
if (model.SelectedCountry.HasValue)
{
var tours = db.Tours.Where(e => e.CountryId == model.SelectedCountry);
model.TourList = new SelectList(tours, "Id", "TourName");
}
else
{
model.TourList = new SelectList(Enumerable.Empty<SelectListItem>());
}
}
and finally in the view (note that both dropdownlists need to be inside the <form> element)
#model TourDateVM
....
#using Html.BeginForm())
{
....
<div class="form-group">
#Html.LabelFor(m => m.SelectedCountry, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedCountry, Model.CountryList, "- Please select -", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedCountry, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.SelectedTour, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedTour, Model.TourList, "- Please select -", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SelectedTour, "", new { #class = "text-danger" })
</div>
</div>
....
}
and the script should be
var url = '#Url.Action("GetT")'; // assumes its in the same controller
var tours = $('#SelectedTour');
$('#SelectedCountry').change(function() {
tours.empty();
$.post(url , { id: $(this).val() }, function(data) {
if (!data) {
return;
}
tours.append($('<option></option>').val('').text('- Please select -'));
$.each(data, function(index, item) {
tours.append($('<option></option>').val(item.Id).text(item.TourName));
});
});
})

Sent form (list object) to controller AJAX MVC

I want sent form (list of object) with ajax. But the function serialize() in JS doesnt read in controller
JS File:
function save() {
$.ajax({
url: "/Ocena/AddOcene",
method: "POST",
dataType: "html",
data: {
id: $("#KlasaDDL option:selected").val(),
dodaj: $('#formOceny').serializeArray()
},
success: function (html) {
$('#load').html(html);
}
})
}
$(function () {
var llBtn = $('#saveForm');
llBtn.click(function () {
save();
});
});
In controller I have parametrs:
public ActionResult AddOcene(string id, List<Dodaj_ocene> dodaj)
View:
#model List<biblioteka.Dodaj_ocene>
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "formOceny" }))
{
#Html.DropDownListFor(x => Model[0].Przedmiot, (SelectList)ViewBag.Przedmiot, "--Dostępne przedmioty--", new { #class = "form-control" })
#*#Html.DropDownList(m => Model[0].Przedmiot, *#
<p>Wprowadź rodzaj</p>
#Html.TextBoxFor(m => Model[0].Rodzaj, new { #class = "form-control" })
<p>Wprowadź Opis</p>
#Html.TextBoxFor(m => Model[0].Opis, new { #class = "form-control" })
<p>Wybierz wagę ocen:</p>
#Html.DropDownListFor(m => Model[0].Waga, new SelectListItem[] {
new SelectListItem{ Value = "5", Text = "V", Selected = Model[0].Waga == 5 } ,
new SelectListItem{ Value = "4", Text = "IV", Selected = Model[0].Waga == 4 } ,
new SelectListItem{ Value = "3", Text = "III" , Selected =
}, new { #class = "form-control" })
<br /> <br />
<table class="table">
<tr>
</tr>
#for (var index = 0; index < Model.Count; index++)
{
<tr>
<td>#Model[index].ImieNazwisko </td>
<td>
#Html.DropDownListFor(m => Model[index].Wartosc, new SelectListItem[]{
new SelectListItem{ Value = "0", Text = "Brak oceny", Selected = Model[index].Wartosc == 0 } ,
new SelectListItem{ Value = "1", Text = "1" , Selected = Model[index].Wartosc == 1 }
} , new { #class = "form-control" })
</td>
</tr>
}
</table>
<div class="form-group">
<div></div>
<button type="button" class="btn btn-info" id="saveForm">Zapisz</button>
</div>
}
I would be very grateful for a Apparently

MVC 5 Ajax form with field updates asynchronously and still supporting a Full form post

So I have been using MVC for a while but not a lot of Ajax.
So the issue i have is that I have a create view where the first field of the create view is a Date picker which on change i want ajax to change the selection dropdown of another field on the form. I have the Ajax update working , but the form Post (Create button), now only calls into the Ajax method on the controller. I want the Ajax post back to call the default method Create method on the Controller. So the Create form contains 3 fields
A date (which has the OnChange Ajax submit)
A drop down list of id's and text
other fields as required
I have included the model and cshtml view files (one the partial). The controller is just simply a method taking either the datetime value or the entire model.
So I have the code working where, when the date changes it updates the relevant LocalIds field, but because the 'create' button is inside the Ajax.BeginForm tags, when the create button is pressed, it generates an Ajax call, and I want it to generate a Form Post. What am i missing
CreateModel
public class IdsSelection
{
public string Id { get; set; }
public List<SelectListItem> Selections { get; set; }
}
public class CreateModel
{
[Display(Name="Local Id's")]
public IdsSelection LocalIds;
[Display(Name="Day")]
[Required, DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",ApplyFormatInEditMode=true)]
public DateTime Date { get; set; }
[Required, Display(Name = "Other Value")]
[Range(1.0, 1000000.0, ErrorMessage ="Value must be greater than zero")]
public decimal OtherValue { get; set; }
public CreateModel()
{
Date = DateTime.Today;
}
}
CreateView.cshtml
#Model Demo.Models.CreateModel
....
#using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "changeid",
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new
{
htmlAttributes = new
{
autofocus = "autofocus",
#class = "form-control",
#Value = Model.Date.ToString("yyyy-MM-dd"),
onchange = "$(this.form).submit();"
}
})
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_ShowIds", Model.LocalIds)
<div class="form-group">
#Html.LabelFor(model => model.OtherValue, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OtherValue, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OtherValue, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
}
_ShowIds.cshtml
#model Demo.Models.IdsSelection
<div id="changeid" class="form-group">
#Html.Label("Local Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#if(Model.Selections.Count == 1) // one
{
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Selections[0].Text, new
{
htmlAttributes = new
{
#class = "form-control",
#readonly = "readonly",
}
})
}
else // more entries so show a dropdown
{
#Html.DropDownListFor(model => model.Id, Model.Selections, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model, "", new { #class = "text-danger" })
}
</div>
</div>
You have not shown you controller methods, but assuming the method which generates this view is named Create(), then create a corresponding POST method
[httpPost]
public ActionResult Create(CreateModel model)
for saving the data. The remove #using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions() { ..... ])) and replace with a normal form to post back to the server (and you can remove jquery.unobtrusive-ajax.min.js)
#using (Html.BeginForm())
{
....
Next create a controller method that returns your partial view based on the selected date
public PartialViewResult FetchLocalIds(DateTime date)
{
IdsSelection model = // populate model based on selected date
return PartialView("_ShowIds", model);
}
Next, in the view, wrap the current #Html.Partial() in a placeholder element
<div id="localids">
#Html.Partial("_ShowIds", Model.LocalIds)
</div>
Then use jquery to handle the datepickers .change() event and call the FetchLocalIds() method to update the DOM using the .load() function.
$('#Date').change(function() {
$('#localids').load('#Url.Action("FetchLocalIds")', { date: $(this).val() })
})
Note also to remove onchange = "$(this.form).submit();" from the #Html.EditorFor(model => model.Date, new { ... })

Ajax.BeginForm only displaying partial View instead of parent & partial view on return

I have a parent View & a child View.
When posing with the Ajax.BeginForm, I'm expecting back the entire parent view plus the results of the partial view updated. Only the results of the partial view is displayed.
In addition, the "OnSuccess" method doesn't seem to be getting hit as I'm debugging.
Can someone please tell me what I'm doing incorrecty?
Controller:
public class HomeController : Controller
{
private DAL db = new DAL();
public ActionResult Index()
{
ViewBag.Message = "Welcome to YeagerTech!";
return View();
}
// GET: Categories/Create
public ActionResult Create()
{
return View();
}
// POST: Categories/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Category category)
{
if (ModelState.IsValid)
{
try
{
await db.AddCategoryAsync(category);
}
catch (System.Exception ex)
{
throw ex;
}
}
return View(category);
}
public PartialViewResult ShowDetails()
{
//string code = Request.Form["txtCode"];
Category cat = new Category();
//foreach (Product p in prodList)
//{
// if (p.ProdCode == code)
// {
// prod = p;
// break;
// }
//}
cat.CategoryID = 1;
cat.Description = "Financial";
return PartialView("_ShowDetails", cat);
}
}
Parent View
#model Models.Models.Category
#{
ViewBag.Title = "Create Category";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create Category</h2>
#using (Ajax.BeginForm("ShowDetails", "Home", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "div1",
InsertionMode = InsertionMode.Replace,
OnSuccess = "OnSuccess",
OnFailure = "OnFailure"
}, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="body-content">
<h4>Category</h4>
<hr />
<div class="form-group">
<div class="col-offset-1 col-lg-11 col-md-11 col-sm-11 col-xs-11">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", #placeholder = "Description" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-lg-11 col-md-11 col-sm-11 col-xs-11">
<button type="submit" id="btnCategoryCreate" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Create</button>
</div>
</div>
</div>
}
<div id="div1">
</div>
#*<div>
#Html.ActionLink("Back to List", "Index")
#Html.Hidden("categoryCreateUrl", Url.Action("Create", "Home"))
</div>*#
#section Scripts {
<script>
$(document).ready(function ()
{
function OnSuccess(response)
{
$('#form1').trigger("reset");
}
//if (typeof contentCreateCategory == "function")
// contentCreateCategory();
});
</script>
}
Partial View
#model Models.Models.Category
<h1>Cat Details</h1>
<h2>
Cat Code: #Model.CategoryID<br />
Cat Name: #Model.Description<br />
</h2>
EDIT # 1
Parent & child view displayed (due to a missing JS file, thanks to the mention of Stephen), plus was able to programmatically clear out the form with the OnSuccess method.
I had thought since that was JS, it needed to go in the Scripts section, but did not recognize it there.
Here is the finished code.
#using (Ajax.BeginForm("ShowDetails", "Home", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "div1",
InsertionMode = InsertionMode.Replace,
OnSuccess = "OnSuccess",
OnFailure = "OnFailure"
}, new { #id = "frm1", #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="body-content">
<h4>Category</h4>
<hr />
<div class="form-group">
<div class="col-offset-1 col-lg-11 col-md-11 col-sm-11 col-xs-11">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", #placeholder = "Description" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-lg-11 col-md-11 col-sm-11 col-xs-11">
<button type="submit" id="btnCategoryCreate" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Create</button>
<button type="reset" id="btnClear" class="btn btn-default"><span class="glyphicon glyphicon-eye-close"></span>Clear</button>
</div>
</div>
</div>
}
<div id="div1">
</div>
<script type="text/javascript">
function OnSuccess(response)
{
$('#frm1').trigger("reset");
}
function OnFailure(response)
{
alert("Whoops! That didn't go so well did it?");
}
</script>
A bit late for answer, but yet it might help someone else.
The issue might be that the javascript files required for Ajax.BeginForm are not loaded in your page.
Microsoft.jQuery.Unobtrusive.Ajax
Nuget package to search for
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.3" targetFramework="net45" />
of course that the version might differ.
Add reference to the page after your jQuery and it should work.

Entity framework update shows dbconcurrency while updating a record?

in my code the update takes place both in the view and in the controller. Same Controller and View for both create and Update. Create profile works fine. but while updating it shows DbConcurrency exception Message. Please help me to find.
Exception Message while updating the record:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
My Update profile page has (Profile.cshtml)
#model Sitecss.Models.Profile
#using Microsoft.Web.Helpers;
#{
ViewBag.Title = "CreateProfile";
Layout = "~/Views/Shared/_HomeLay.cshtml";
}
#{
var GT = new SelectList(new[] {
new {ID ="Team DeathMatch", Name="Team DeathMatch"},
new {ID ="Search & Destroy", Name="Search & Destroy"},
new {ID ="Flag Runner", Name="Flag Runner"},
new {ID ="Domination", Name="Domination"},
new {ID ="Kill Confirmed", Name="Kill Confirmed"}
},"ID","Name");
var Spec = new SelectList(new []{
new {ID ="Assault", Name="Assault"},
new {ID ="Tactical", Name="Tactical"},
new {ID ="Long-Range Eliminations", Name="Long-Range Eliminations"},
new {ID ="Noob", Name="Noob"}
}, "ID", "Name");
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm("CreateProfile", "Home", FormMethod.Post, new { #encType = "multipart/form-data" }))
{
<div id="content1">
#Html.ValidationSummary(true)
<h4>Create a Profile</h4>
<div>
#Html.LabelFor(m => m.SteamName)
</div>
<div>
#Html.TextBoxFor(m => m.SteamName, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.SteamName)
</div>
<div>
#Html.LabelFor(m =>m.UserImg)
</div>
<div>
<input type="file" name="image" class="image" /> <br />
</div>
<div>
#Html.LabelFor(m => m.GameType)
</div>
<div>
#Html.DropDownListFor(m => m.GameType, GT, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.GameType)
</div>
<div>
#Html.LabelFor(m => m.Specialist)
</div>
<div>
#Html.DropDownListFor(m => m.Specialist, Spec, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.Specialist)
</div>
<div>
#Html.LabelFor(m => m.FavGun)
</div>
<div>
#Html.TextBoxFor(m => m.FavGun, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.FavGun)
</div>
<p><input type="submit" class="button" value="Ok" /></p>
</div>
}
while my controller functions are
public ActionResult CreateProfile()
{
if (db.Profiles.Any(u => u.Username == User.Identity.Name))
{
Profile pro = (from usr in db.Profiles where usr.Username == User.Identity.Name select usr).Single();
olf = pro.UserImg;
Profile p = db.Profiles.Find(pro.Id);
ViewBag.ProfilePic = olf;
return View(p);
}
else
{
ViewBag.Name = User.Identity.Name;
return View();
}
}
[HttpPost]
public ActionResult CreateProfile(Profile m)
{
WebImage photo = WebImage.GetImageFromRequest();
string newFileName = "";
string thumbs = "";
if (photo != null)
{
string ext = Path.GetExtension(photo.FileName);
newFileName = User.Identity.Name+ ext;
thumbs = #"Images/" + newFileName;
photo.Resize(width: 120, height: 120, preserveAspectRatio: true, preventEnlarge: true);
photo.Save(#"~/"+thumbs);
m.UserImg = newFileName;
}
if (ModelState.IsValid)
{
if (db.Profiles.Any(u => u.Username == User.Identity.Name))
{
db.Entry(m).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
m.Username = User.Identity.Name;
db.Profiles.Add(m);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(m);
}
While Adding Breakpoint to the update statement in my edit Controller I came to know that the primary key Id =0 on update in order to fix this issue I have added Hidden Field in the view that has fixed the DbConcurrency on update

Resources