我对具有多对多关系的作者和书籍做了类似的事情。基本思想是从视图中创建一个 JSON 对象,其中包含其中的所有作者并提交给控制器。我还使用 jQuery UI TagIt 来允许用户添加/删除与本书相关的作者。当用户单击“保存图书”按钮时,脚本会构建一个模仿图书对象的 JSON 对象。
下面是代码。在尝试此代码之前,请确保您已在项目中添加了“json2.js”和“tagit.js”。
查看型号:
public class BookViewModel
{
public string Title { get; set; }
public int BookId { get; set; }
public int IsAvail { get; set; }
public string CallNumber { get; set; }
//Assiged authors
public List<AuthorViewModel> Authors { get; set; }
//available authors
public List<AuthorViewModel> AuthorOptions { get; set; }
}
public class AuthorViewModel
{
public int AuthorId { get; set; }
public string FirstName { get; set; }
}
Book/Edit.chtml 的代码:
@using System.Web.Script.Serialization
@model eLibrary.Models.BookViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<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>
@*This is for JSON*@
<script src="../../Scripts/json2.js" type="text/javascript"></script>
<script src="../../Scripts/tagit.js" type="text/javascript"></script>
@*These are for styling Control*@
<link href="../../Content/themes/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
//This function is used for sending data(JSON Data) to BookController
function BookSave() {
// Step 1: Read View Data and Create JSON Object
var author = { "AuthorId": "", "FirstName": "" };
// Creating book Json Object
var book = { "BookId": "", "Title": "", "IsAvail": "", "CallNumber":"", "authors": []};
// Set Boook Value
book.BookId = $("#BookId").val();
book.Title = $("#Title").val();
book.IsAvail = $("#IsAvail").val();
book.CallNumber = $("#CallNumber").val() ;
var tags = $('#authors').tagit('tags');
for (var i in tags) {
author.AuthorId = tags[i].value;
author.FirstName = tags[i].label;
book.authors.push(author );
author = { "AuthorId": "", "FirstName": "" };
}
// Step 1: Ends Here
// Set 2: Ajax Post
// Here i have used ajax post for saving/updating information
$.ajax({
url: '/Book/Edit',
data: JSON.stringify(book),
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function (result) {
if (result.Success == "1") {
window.location.href = "/Book/Edit";
}
else {
alert(result.ex);
}
}
});
}
</script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Book Details</legend>
@Html.HiddenFor(model => model.BookId)
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsAvail)
</div>
@Html.EditorFor(model => model.IsAvail)
@Html.ValidationMessageFor(model => model.IsAvail)
@Html.EditorFor(model => model.CallNumber);
</fieldset>
@Html.Partial("AuthorsByBook", Model.Authors, new ViewDataDictionary { { "mode", "EDIT" } })
<input type="button" value="Book Save" onclick="BookSave()" />
}
Book/AuthorsByBook.chtml 的代码
@model IEnumerable< eLibrary.Models.AuthorViewModel>
<link href="../../Content/tagit-awesome-blue.css" rel="stylesheet" type="text/css" />
<div class="box">
<ul id="authors" name="authors">
</ul>
</div>
<script type="text/javascript">
//Load authors in the javascript variable
$(function () {
var initialAuthorList=[];
@if(ViewData["mode"]=="EDIT")
{
foreach (var category in Model)
{
<text>
initialAuthorList.push({label: "@category.FirstName", value: @category.AuthorId });
</text>
}
}
$('#authors').tagit({tagSource: function (request, response) {
$.ajax({
url: "/Author/SearchAuthor", type: "POST", dataType: "json",
data: { searchText: request.term, maxResults: 10 },
success: function (data) {
response($.map(data, function (item) {
return { label: item.FirstName, value: item.AuthorId }
}))
}
})
},
initialTags:initialAuthorList,minLength:3,allowNewTags:false,sortable:true,delay:400});
});
</script>
BookController.cs 的代码
public ActionResult Edit(int id)
{
//To DO: use repository to fetch data
Book book = db.Books.Single(a => a.BookId == id);
Mapper.CreateMap<Book, BookViewModel>();
Mapper.CreateMap<Author, AuthorViewModel>();
BookViewModel bookVm = Mapper.Map<Book, BookViewModel>(book);
List<AuthorViewModel> Authors = Mapper.Map<List<Author>,List<AuthorViewModel>>( db.Authors.ToList());
bookVm.AuthorOptions = Authors;
return View(bookVm);
}
[HttpPost]
public ActionResult Edit(BookViewModel bookv)
{
//create maps
Mapper.CreateMap<AuthorViewModel, Author>();
Mapper.CreateMap<BookViewModel, Book>();
//convert view objects to model objects
Book book = Mapper.Map<BookViewModel, Book>(bookv);
List<Author> authors = Mapper.Map<List<AuthorViewModel>, List<Author>>(bookv.Authors.ToList());
//this has to be executed before db.Books.Attach
//clear authors
book.Authors.Clear();
db.Books.Attach(book);
//assign authors to book
foreach (Author a in authors) { db.Authors.Attach(a); }
book.Authors.Clear();
foreach (Author a in authors) { book.Authors.Add(a); }
db.ObjectStateManager.ChangeObjectState(book, EntityState.Modified);
db.SaveChanges();
return RedirectToAction("Index");
}
AuthorController.cs 中 SearchAuthor 方法的代码
public JsonResult SearchAuthor(string searchText, int? maxResults)
{
IEnumerable<Author> query = db.Authors;
searchText = searchText.ToLower();
query = query.Where(c => c.FirstName.ToLower().Contains(searchText));
if ((maxResults ?? 0) == 0)
{
return Json(query.ToList());
}
else
{
return Json(query.Take((int)maxResults).ToList());
}
}