Выполнение операций создания на двух моделях с помощью одного действия

StackOverflow https://stackoverflow.com/questions/8310746

Вопрос

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

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

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

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

Это было полезно?

Решение 2

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

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

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

    public class CatPicView
    {
        public Category Category { get; set; }
        public Picture Picture { get; set; }
    }
    
  • Во -вторых, я добавил Загрузить 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);
    }
    
  • И, наконец, переписайте категорию, создайте функцию, как показано ниже для сохранения изменений в DB

    [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();
    }
    

Другие советы

Создайте модель, как это:

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");
}

Я думаю, что функция каркасов 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>
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top