MVC5 Azure BLOB-объектов и моделей
Здравствуйте! У меня есть функция для сохранения текста и изображений из форм в базу данных Azure SQL (текст) и в BLOB-объекты Azure для моих изображений. Кроме того, он размещается в облаке в Azure, и его сохранение и загрузка отлично работает. Запуск в обычном стеке C# EF MVC5 Bootstrap Vanilla js, веб-ролик BLOB-объектов Azure и т. Д.
Я застрял в области, которую не могу понять - отобразить мою модель представления (это модель представления с двумя объектами EF, т.е. двумя таблицами базы данных) вместе со списком BLOB-объектов (объект BLOB-объекта Azure). Из-за того, что они не являются технически одинаковыми типами контекста, это проблема, но как мы можем объединить их и вывести так:
Обратный просмотр (jobsVModel + Blobs);
Вот моя текущая работа: Модель:
namespace client.Models
{
public class JoinUsersandJobsModel : DbContext
{
public tradesusers tradesusers { get; set; }
public jobs jobs { get; set; }
public uploadedfiles uploadedfiles { get; set; }
//add a blob service to our model
//public BlobProfileImageServices _blobServices = new BlobProfileImageServices();
}
}
У меня есть мой контроллер:
private traderEntities db = new traderEntities();
BlobProfileImageServices _blobServices = new BlobProfileImageServices();
public ActionResult Index(string usernameCookie)
{
var viewModel = from u in db.tradesusers
join j in db.jobs on u.id equals j.jobbyuserid
join pic in db.uploadedfiles on j.id equals pic.ImageId
where u.email.Equals(usernameCookie)
select new JoinUsersandJobsModel { tradesusers = u, jobs = j, uploadedfiles = pic };
//blob container
List<ImageVM> images;
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
List<string> blobs = new List<string>();
foreach (var blobItem in blobContainer.ListBlobs())
{
blobs.Add(blobItem.Uri.ToString());
}
images = blobs
// convert an Azure blob record into an ImageVM:
.Select(b => new ImageVM()
{
})
.ToList();
//return View(blobs);
//return View(imageModel);
//List<Object> allS = (from x in viewModel select (Object)x).ToList();
//allS.AddRange((from x in blobs select (Object)x).ToList());
return View(images);
//return View(db.tradesusers.ToList());
}
Как вы можете видеть выше, я хочу вернуть два объекта одновременно, один из которых называется "blob", а второй - "viewModel", но мы можем видеть, что это два разных типа объектов! 'Return View(viewModel.ToList());' один работает, как и "Return View(blob);".
Мой взгляд:
@model IEnumerable<traderclient.Models.JoinUsersandJobsModel>
<--!@model2 List<traderclient.Models.ImageVM>-->
@{
ViewBag.Title = "Profile";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>system - Client's Profile</title>
</head>
<body>
<br /><br /><br /><br /><br />
<h1>Profile</h1>
@foreach (var item in Model)
{
<div>
<h5> Profile pic</h5>
<hr />
<dl class="dl-horizontal">
<dt>
Pic
</dt>
<dt>
</dt>
<dd>
<img src="@Url.Content(@item.uploadedfiles.ImagePath+@item.uploadedfiles.ImageName)" width="250" height="250" multiple />
</dd>
</dl>
<p>
@Html.ActionLink("Edit", "Edit", new { id = @item }) |
@Html.ActionLink("Back to List", "Index")
</p>
</div> }
<table>
<tr>
<td>
<table class="table" style="width:200px;">
<tr>
<td style="width:50%"> Image </td>
<td style="width:25%"> Delete </td>
</tr>
<ul style="list-style-type:none; padding:0;">
@foreach (var item in model2)
{
<tr>
<td> <img src="@item." alt="image here is" width="100" height="100" /> </td>
<td> <input type="button" id="@item." onclick="deleteImage('@item');" value="Delete" /></td>
</tr>
}
</ul>
</table>
</td>
<td style="width:100px"></td>
</tr>
</table>
Снова выше в представлении, использующем только ОДНУ определение модели, работает так, т.е. IEnumerable для таблиц заданий или торговцев или если я ТОЛЬКО использую объект List для объекта изображения Blob, который тоже работает. Но, как и контроллер, я не могу объединить их. Как я уже упоминал, остальные данные (все данные, кроме большого двоичного объекта) хранятся в базе данных SQL Azure. В Azure Blobs живут только изображения.
Не забудьте мое определение для моих BLOB-объектов, которое также находится в корне этого проекта как отдельный класс:
2 ответа
Исправлено в конце / предоставлен обходной путь. Таким образом, ваш ответ немного помог, но не достаточно @Dai
Чтобы исправить это сделать: Модель:
// МОДЕЛИ SQL
// Имя файла: JoinUsersandJobsModel.cs
namespace client.Models
{
public class JoinUsersandJobsModel : DbContext
{
public tradesusers tradesusers { get; set; }
public jobs jobs { get; set; }
public uploadedfiles uploadedfiles { get; set; }
//Blob service does not need to be here
}
}
// FileModel - это дополнительная модель для обработки данных BLOB
// Имя файла: FileListModel.cs
namespace client.Models
{
public class FileListModel
{
public FileListModel(IEnumerable<IListBlobItem> list)
{
if (list != null)
{
Files = new List<FileInfo>();
foreach (var item in list)
{
FileInfo info = FileInfo.CreateFromIListBlobItem(item);
if (info != null)
{
Files.Add(info);
}
}
}
}
public List<FileInfo> Files { get; set; }
}
public class FileInfo
{
public string FileName { get; set; }
public string URL { get; set; }
public long Size { get; set; }
public static FileInfo CreateFromIListBlobItem(IListBlobItem item)
{
if (item is CloudBlockBlob)
{
var blob = (CloudBlockBlob)item;
return new FileInfo { FileName = blob.Name,
URL = blob.Uri.ToString(),
Size = blob.Properties.Length };
}
return null;
}
}
}
// Контроллер для Azure SQL
private traderEntities db = new traderEntities();
BlobProfileImageServices _blobServices = new BlobProfileImageServices();
public ActionResult Index(string usernameCookie)
{
var viewModel = from u in db.tradesusers
join j in db.jobs on u.id equals j.jobbyuserid
where u.email.Equals(usernameCookie)
select new JoinUsersandJobsModel { tradesusers = u, jobs = j, uploadedfiles = pic };
return View(viewModel);
}
// Контроллер для BLOB-объектов Azure
// Завершаем отбрасывание частичного и возвратного BLOB-объектов того же типа действия
// и модельных блобов (Blobs)
// Позже мы встраиваем частичное в клиент
public ActionResult loadMyBlob()
{
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
List<string> blobs = new List<string>();
foreach (var blobItem in blobContainer.ListBlobs())
{
blobs.Add(blobItem.Uri.ToString());
}
return PartialView("loadMyBlob", blobs);
}
// Создаем нашу Частично Сильно Типированную и Проверяем нашу Модель для BLOB-объектов
@model yourApp.Models.FileListModel
@{
ViewBag.Title = "File List";
}
<h2>File List</h2>
<ul>
@foreach (var item in Model.Files)
{
<li>
<a href="@item.URL">@item.FileName</a> (@item.Size bytes)
</li>
}
</ul>
@Html.ActionLink("Upload Another File", "UploadFile")
// Наконец-то внедряем наше Частичное в представление действия - "Индекс" в нашем случае
// Код для встраивания можно разместить в любом месте вашего представления
// Действие будет выполнено по запросу и через блоб
<embed src='@Url.Action("loadMyBlob", "Profile")'>
Если кому-то нужна помощь в подобной настройке, пожалуйста, дайте мне знать.
Ссылка: ТАКЖЕ поддержу и спасибо Джону Килиберти, где я скопировал его идею из его книги для класса FileListModel и как отобразить ее в представлении.
Вы не должны использовать свои внутренние объекты (будь то Microsoft.WindowsAzure.Storage.*
объекты) или ваши собственные объекты базы данных) как ViewModels - вы должны создать новые классы ViewModel для каждого компонента логического представления (представление, частичный, повторяющийся элемент и т. д.) и заполнить их внутри ваших действий контроллера данными из ваших внутренних объектов.
Например, если у вас есть представление, которое показывает список изображений, то это будет выглядеть так:
class ImagesController : Controller {
public ActionResult Index() {
List<ImageVM> images;
if( useAzure ) {
List<CloudStorageBlob> blobs = GetBlobs( ... );
images = blobs
// convert an Azure blob record into an ImageVM:
.Select( b => new ImageVM()
{
Url = b.BlobUrl
} )
.ToList();
}
else { // use local SQL
List<MyImageEntity> dbImages = GetImagesFromDB( ... );
images = dbImages
// convert a database MyImageEntity into an ImageVM:
.Select( i => new ImageVM()
{
Url = i.ImageAddress
} )
.ToList();
}
return this.View( images );
}
}
ViewModels:
public class ImageVM {
public String Url { get; set; }
public String TitleText { get; set; }
public String Etc { get; set; }
}
Посмотреть:
@model List<ImageVM>
<ul>
@foreach(ImageVM image in this.Model) {
<li><img src="@image.Url" title="@image.TitleText" /></li>
}
</ul>