我似乎无法在我的应用程序中显示每个帖子的单独图片。所有图像都与列表中的最后一个图像相同。我需要将每个Pictures
的{{1}}转换为base64。在控制器中,我试图抓取每个帖子对象并将Picture属性转换为base64,然后将其添加到post
,但是ViewBag.ImageToShow
只能容纳一个项目,所以我的所有图像都设置为最后一个图像我的ImageToShow
列表。如果我为posts
创建list<string>
作为下面提到的答案之一,我就不知道如何正确索引它们。
型号:
ViewBag
控制器:
public partial class Post
{
public Post()
{
this.Tags = new HashSet<Tag>();
}
public int Id { get; set; }
public string BlogUserEmail { get; set; }
public int CategoryId { get; set; }
public string Title { get; set; }
public string ShortDescription { get; set; }
public string Description { get; set; }
public string Meta { get; set; }
public string UrlSlug { get; set; }
public bool Published { get; set; }
public System.DateTime PostedOn { get; set; }
public Nullable<System.DateTime> Modified { get; set; }
public byte[] Picture { get; set; }
public virtual BlogUser BlogUser { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
}
查看:
public ActionResult Index()
{
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name).Include(p => p.BlogUser).Include(p => p.Category);
foreach (var item in posts) // this is wrong
{
byte[] buffer = item.Picture;
ViewBag.ImageToShow = Convert.ToBase64String(buffer);
}
return View(posts.ToList());
}
请注意,在我创建动态布局时,我将@for (int i = 0; i < Model.Count(); i += 3)
{
<div class="row">
@foreach (var item in Model.Skip(i).Take(3))
{
<div class="col-md-4 portfolio-item">
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">
<img class="img-responsive" src="@Html.Raw("data:image/jpeg;base64," + ViewBag.ImageToShow)" alt="">
</a>
<h3>
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">@Html.DisplayFor(modelItem => item.Title)</a>
</h3>
<p>@Html.DisplayFor(modelItem => item.ShortDescription)</p>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { urlslug = item.UrlSlug }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</div>
}
</div>
}
放在foreach循环中。对于帖子列表中的每个图像显示图像。但是我无法将viewbag作为列表存储并返回与视图foreach相关的正确图像,同时必须将图像转换为base64。
答案 0 :(得分:3)
您的代码问题在于控制器中Index函数的循环。你在循环中设置ViewBag.ImageToShow
,这个变量只能容纳一个对象,因此通过在循环中设置它不断重置。
这里有两个选项:
使用ViewBag
在您的控制器中,创建一个分别包含int, string
,ID和值的词典。在循环内部,您需要为找到的每个图像添加一个条目。
public ActionResult Index()
{
Dictionary<int, string> postImages = new Dictionary<int, string>();
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name).Include(p => p.BlogUser).Include(p => p.Category);
foreach (var item in posts)
{
byte[] buffer = item.Picture;
postImages.Add(item.ID, Convert.ToBase64String(buffer));
}
ViewBag.Images = postImages;
return View(posts.ToList());
}
在你的视图中,你应该在开始循环之前声明一个包含列表的局部变量:
var images = (Dictionary<int, string>)ViewBag.Images;
现在,在循环中,您可以从列表中获得所需的图像:
images.Single(i => i.Key == item.ID).Value;
按要求提供完整示例:
@{Dictionary<int, string> images = (Dictionary<int, string>)ViewBag.Images;
@for (int i = 0; i < Model.Count(); i += 3)
{
<div class="row">
@foreach (var item in Model.Skip(i).Take(3))
{
<div class="col-md-4 portfolio-item">
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">
<img class="img-responsive" src="@Html.Raw("data:image/jpeg;base64," + images.Single(image => image.Key == item.ID).Value)" alt="">
</a>
<h3>
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">@Html.DisplayFor(modelItem => item.Title)</a>
</h3>
<p>@Html.DisplayFor(modelItem => item.ShortDescription)</p>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { urlslug = item.UrlSlug }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</div>
}
</div>
}
}
使用第二个模型
我个人以前从未使用过这个,但我已经看过它,我想我只是提到它。
要使用此技术,您必须创建第二个模型,此模型将保留原始模型和图像。
public class PostImageModel
{
public Post Post { get; set; }
public string Image { get; set; }
}
现在在控制器内部,我们必须创建一个新创建的模型列表,并用所需的数据填充它:
public ActionResult Index()
{
List<PostImageModel> postsWithImages = new List<PostImageModel>();
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name).Include(p => p.BlogUser).Include(p => p.Category);
foreach (var item in posts)
{
item.Picture = null;
postsWithImages.Add(new PostImageModel()
{
Post = item,
Image = Convert.ToBase64String(item.Picture)
});
}
return View(postsWithImages);
}
编辑:添加,以便代码在完成转换后清空字节数组。 (谢谢@Serv)。
您的循环将保持不变,除了使用item.Title
之外,您现在应该使用item.Post.Title
。
请注意,您现在应该在视图顶部添加@model ExampleNamespace.Models.PostImageModel
以使用此模型。
答案 1 :(得分:2)
您正在将每张图片分配给相同的ViewBag属性,这是正常的,您始终可以看到相同的图片。
您应该向模型添加一个名为ImageToShow的新字符串属性,标记为NotMapped属性:
public partial class Post
{
public Post()
{
this.Tags = new HashSet<Tag>();
}
public int Id { get; set; }
public string BlogUserEmail { get; set; }
public int CategoryId { get; set; }
public string Title { get; set; }
public string ShortDescription { get; set; }
public string Description { get; set; }
public string Meta { get; set; }
public string UrlSlug { get; set; }
public bool Published { get; set; }
public System.DateTime PostedOn { get; set; }
public Nullable<System.DateTime> Modified { get; set; }
public byte[] Picture { get; set; }
[NotMapped]
public string ImageToShow { get; set; }
public virtual BlogUser BlogUser { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
控制器:
public ActionResult Index()
{
var posts = new List<MvcApplication2.Models.Post>();
foreach (var item in posts) // this is wrong
{
byte[] buffer = item.Picture;
item.ImageToShow = Convert.ToBase64String(buffer);
}
return View(posts.ToList());
}
查看:
@for (int i = 0; i < Model.Count(); i += 3)
{
<div class="row">
@foreach (var item in Model.Skip(i).Take(3))
{
<div class="col-md-4 portfolio-item">
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">
<img class="img-responsive" src="@Html.Raw("data:image/jpeg;base64," + item.ImageToShow)" alt="">
</a>
<h3>
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">@Html.DisplayFor(modelItem => item.Title)</a>
</h3>
<p>@Html.DisplayFor(modelItem => item.ShortDescription)</p>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { urlslug = item.UrlSlug }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</div>
}
</div>
}
答案 2 :(得分:1)
有几种方法可以做到这一点。第一个也是最快的是将所有图像放在一个集合中,然后将该集合存储在ViewBag中。现在,你只存储一个图像 - 最后一个。
public ActionResult Index()
{
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name).Include(p => p.BlogUser).Include(p => p.Category);
// create collection
List<string> ImageCollection = new List<string>();
foreach (var item in posts)
{
//add images to list
ImmageCollection.Add(Convert.ToBase64String(item.Picture));
}
//Add list to ViewBag
ViewBag.ImageToShow = ImageCollection;
return View(posts.ToList());
}
现在您可以使用迭代器在视图中访问它:
<img class="img-responsive" src="@Html.Raw("data:image/jpeg;base64," + ViewBag.ImageToShow[i])" alt="">
就个人而言,我为此创建了一个ViewModel,因为您不会使用Post
类的所有属性。
创建一个包装所需属性的类。让我们称之为PortfolioVM:
public class PortfolioVM
{
public int Id { get; set; }
public string UrlSlug { get; set; }
//not Byte[]!
public string Picture { get; set; }
public string ShortDescription { get; set; }
}
现在在你的控制器中我们将使用ViewModel:
public ActionResult Index()
{
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name)
.Include(p => p.BlogUser)
.Include(p => p.Category)
.Select(vm => new PortfolioVM(){
Id = vm.Id,
UrlSlug = vm.UrlSlug,
Picture = Convert.ToBase64String(vm.Picture),
ShortDescription = vm.ShortDescprition
}) ;
return View(posts);
}
现在我们需要更改您的视图,以使用新的ViewModel。将声明模型的第一行更改为:
//insert correct namespace!
@model IEnumerable<Namespace.Subfolder.PortfolioVM)
在此之后,您可以像查看视图的其他所有属性一样显示图像:
@foreach (var item in Model.Skip(i).Take(3))
{
<div class="col-md-4 portfolio-item">
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">
<img class="img-responsive" src="@Html.Raw("data:image/jpeg;base64," + item.Picture)" alt="">
</a>
<h3>
<a href="@Url.Action("Details", "Post", new { urlslug = item.UrlSlug })">@Html.DisplayFor(modelItem => item.Title)</a>
</h3>
<p>@Html.DisplayFor(modelItem => item.ShortDescription)</p>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
@Html.ActionLink("Details", "Details", new { urlslug = item.UrlSlug }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id })
</div>
}
答案 3 :(得分:-3)
你做错了!将所有图像存储在同一个变量中!
public ActionResult Index()
{
var posts = db.Posts.Where(p => p.BlogUserEmail == User.Identity.Name).Include(p => p.BlogUser).Include(p => p.Category);
// this is what you should do, or something like this
ViewBag.ImagesToShow = new List<String>();
foreach (var item in posts)
{
byte[] buffer = item.Picture;
// this is really wrong!
//ViewBag.ImageToShow = Convert.ToBase64String(buffer);
ViewBag.ImagesToShow.Add(Convert.ToBase64String(buffer));
}
return View(posts.ToList());
}
您还需要更改视图