Выполнение операций создания на двух моделях одним действием - PullRequest
2 голосов
/ 29 ноября 2011

У меня есть две модели: Категория и Изображение , которое относится к двум таблицам, категориям и изображениям соответственно.Модель Category имеет свойство навигации к модели Picture.

Теперь я создал контроллер, используя функцию Scaffolding с операциями CRUD для Category.Ниже приведен код: -

public ActionResult Create()
{
    ViewBag.ParentCategoryId = new SelectList(db.Categories, "Id", "Name");
    ViewBag.PictureId = new SelectList(db.Pictures, "Id", "PictureUrl");
    return View();
}

Автоматически сгенерированные действия контроллера используют SelectList для отображения списка доступных записей изображений в базе данных и передают его в раскрывающийся список для выбора.Это не идеальный сценарий, поскольку я хочу, чтобы пользователь не смог загрузить изображение, а затем ссылка была добавлена ​​в модель категории.Позже записи сохраняются в таблице категорий и изображений.

Ответы [ 3 ]

5 голосов
/ 05 декабря 2011

Создать такую ​​модель:

public class FullCategoryModel
{
    public HttpPostedFileBase Picture { get; set; }
    public Category CategoryModel {get; set;}
}

В поле зрения:

@using (Html.BeginForm("Create", "Category", FormMethod.Post, 
    new { enctype = "multipart/form-data" }))
{  
  @Html.TextBoxFor(model => model.Category.Name)      // example, put there all category details 
  <input type="file" name="Picture" id="Picture" />      
  <input type="submit" value="Upload" />    

}

Затем создайте действие:

[ActionName("Create")]
[HttpPost]
public ActionResult Create(FullCategoryModel model)
{
// here you can get image in bytes and save it in db, 
// also all category detail are avalliable here

MemoryStream ms = new MemoryStream();
model.Picture.InputStream.CopyTo(ms);
Image picture = System.Drawing.Image.FromStream(ms);

// save in db as separate objects, than redirect
return RedirectToAction("Index", "Category");
}
2 голосов
/ 07 декабря 2011

Прежде всего, я хотел бы поблагодарить @ NickLarsen за то, что заставил меня поверить в то, что мое понимание хорошо и я могу выполнить задачу сам.

Проблема была не в том, что она слишком сложнано так как я был новичком в Asp.net MVC, все было немного странно.С самого начала у меня была идея, что мне понадобятся ViewModel, объединяющие классы Category и Price, а затем API загрузки изображений.Но, так или иначе, я не смог расставить фигуры в нужном месте.Поэтому после различных регрессий и исследований в Интернете я выполнил задачу следующим образом: -

  • Прежде всего, я создал ViewModel

    public class CatPicView
    {
        public Category Category { get; set; }
        public Picture Picture { get; set; }
    }
    
  • Во-вторых, я добавил Uploadify JavaScript API

    <script type="text/javascript">
        $('#file_upload').uploadify({
            'uploader': '@Url.Content("~/uploadify/uploadify.swf")',
            'script': '@Url.Action("Upload", "Category")',
            'cancelImg': '@Url.Content("~/uploadify/cancel.png")',
            'buttonText': 'Upload',
            'folder': '@Url.Content("~/content/images")',
            'fileDesc': 'Image Files',
            'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
            'auto': true,
            'onComplete': function (event, ID, fileObj, response, data) {
                    var json = jQuery.parseJSON(response);
                    $("#pictureImage").html("<img src='"+json+"' alt='"+json+"' height='100px' width='100px'/>");
                    $("#Picture_PictureUrl").val(json);
                    $("#pictureRemove").show();
                }
            });
    </script>
    
  • Подключил API к следующей серверной функции для переименования и сохранения в папку

    [HttpPost]
    public ActionResult Upload(HttpPostedFileBase fileData)
    {
        if (fileData != null && fileData.ContentLength > 0)
        {
            //var fileName = Server.MapPath("~/Content/Images/" + Path.GetFileName(fileData.FileName));
            int pictureCount = 800000;
            pictureCount += db.Pictures.Count();
            string extension = Path.GetExtension(fileData.FileName);
            string renamedImage = Server.MapPath("~/Content/Images/Categories/cat" + pictureCount + extension);
            fileData.SaveAs(renamedImage);
            return Json("/Content/Images/Categories/" + Path.GetFileName(renamedImage));
        }
        return Json(false);
    }
    
  • И наконец, переписали функцию создания категории, как показано ниже, для сохранения изменений в БД

    [HttpPost]
    public ActionResult Create(CatPicView catPic)
    {
        if (ModelState.IsValid)
        {
            if (!String.IsNullOrEmpty(catPic.Picture.PictureUrl))
            {
                Picture picture = new Picture();
                picture.PictureUrl = catPic.Picture.PictureUrl;
                db.Pictures.Add(picture);
                catPic.Category.PictureId = picture.Id;
            }
            db.Categories.Add(catPic.Category);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View();
    }
    
0 голосов
/ 02 декабря 2011

Я думаю, что особенность MVC-скаффолдинга заключается в том, что две модели видят отношение «многие ко многим».Вот почему он создал два выпадающих списка для вас.В соответствии с вашим сценарием, вы можете создать страницу «Категория» без данных модели «Изображение», потому что «Изображение» здесь является основным объектом.Так что на картинке создай действие.

[HttpPost]
    public ActionResult Create(Picture picture)
    {
        if (ModelState.IsValid)
        {
            databaseContext.Pictures.Add(picture);
            databaseContext.SaveChanges();
            return RedirectToAction("Index");  
        }

        return View(picture);
    }

На странице просмотра изображения

@model YourProjectName.Models.Picture
<h2>Create</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
    <legend>Picture</legend>
    <div class="editor-label">
        @Html.LabelFor(model => model.Url)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Url)
        @Html.ValidationMessageFor(model => model.Url)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.Categories.CategoryID, "Category")
    </div>
    <div class="editor-field">
        @Html.DropDownList("CategoryID", "Choose Category")
        @Html.ValidationMessageFor(model => model.Categories.CategoryID)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}
...