To create the script already with initialPreview
completed you do not have to create a method that returns JSON. It will be more efficient to modify the View that today generates the page to use a template, and in that template generate that script dynamically. There are several ways to implement this result. I'll do the most up-to-date first.
ViewBag
Let's fill ViewBag
, a dynamic item that can be filled with all data type and is available to the page rendering engine, in this case Razor. As we are using this simpler way of passing data to the View, I have added the Image class directly in HomeController
(in this case the controller name and action will certainly be different!):
public class HomeController : Controller
{
public class Imagem
{
public int Id { get; set; }
public string Url { get; set; }
}
public ActionResult Index() {
// usando ViewBag... (propriedade dinâmica)
ViewBag.Images = new List<Imagem> {
new Imagem { Id = 1, Url = Url.Content("~/Content/img/galeriaimagens/sl1.jpg") },
new Imagem { Id = 2, Url = Url.Content("~/Content/img/galeriaimagens/sl2.jpg") },
new Imagem { Id = 3, Url = Url.Content("~/Content/img/galeriaimagens/sl3.jpg") },
};
return View();
}
And then in the view we use ViewBag.Images to render the list of urls we'll put in the initial preview . Note that you should set the using
clause at the beginning of the script to use the controller where you defined the class Imagem
:
@using SO_InitialPreviewMVC.Controllers;
@{
ViewBag.Title = "Home Page";
// estou já convertendo para o tipo específico para facilitar mais embaixo
var imgs = ViewBag.Images as List<HomeController.Imagem>;
}
<script>
$("#Image1").fileinput({
uploadUrl: "@Url.Action("upload", "Home")",
uploadAsync: false,
minFileCount: 2,
maxFileCount: 5,
overwriteInitial: false,
initialPreview: [
@* Aqui using string.Join para montar os itens do array, tem um milhão de formas de fazer isso! *@
@Html.Raw(string.Join(",\r\n ",
imgs.Select(img => "\"<img style='height:160px' src='" + img.Url + "'>\"")))
],
initialPreviewConfig: [
{ caption: "Food-1.jpg", size: 329892, width: "120px", url: "@Url.Action("remover", "Home")", key: 1 },
{ caption: "Food-2.jpg", size: 872378, width: "120px", url: "@Url.Action("remover", "Home")", key: 2 },
{ caption: "Food-3.jpg", size: 632762, width: "120px", url: "@Url.Action("remover", "Home")", key: 3 },
{ caption: "Food-4.jpg", size: 632762, width: "120px", url: "@Url.Action("remover", "Home")", key: 4 },
],
uploadExtraData: {
img_key: "1000",
img_keywords: "happy, nature",
}
});
</script>
The rest of the view code has been omitted ... I left enough to understand where the changes were made.
View Model
This is what I would indicate as the best way. Let's create a template that we'll call View Model because it's the "vision" model and not the business model. It is used to facilitate view rendering and even carry validation information (in rare cases) and other things.
Let's add the HomeViewModel class in the Models directory of your solution:
public class HomeViewModel
{
public HomeViewModel() {
// apenas para garantir que NUNCA seja nulo! Facilica código na view
PreviewImages = new List<Imagem>();
}
public List<Imagem> PreviewImages { get; set; }
}
Add in the namespace of your application! Use instead of "Home" the name of your View to maintain consistency !!!
Add in Models the same Image class (which we removed from HomeController, since it will now be used by our HomeViewModel
and probably other view models !):
public class Imagem
{
public int Id { get; set; }
public string Url { get; set; }
}
Modify the controller method to pass the template to the heavily typed view:
...
// adicione o using do seus Models (seu namespace será outro!!!)
using SO_InitialPreviewMVC.Models;
...
public ActionResult Index() {
// usando um modelo específico para a view
var model = new HomeViewModel {
PreviewImages = new List<Imagem> {
new Imagem { Id = 1, Url = Url.Content("~/Content/img/galeriaimagens/sl1.jpg") },
new Imagem { Id = 2, Url = Url.Content("~/Content/img/galeriaimagens/sl2.jpg") },
new Imagem { Id = 3, Url = Url.Content("~/Content/img/galeriaimagens/sl3.jpg") },
}
};
// passamos o modelo criado para a view
return View(model);
}
Now modify the view so that it is strongly typed:
@model SO_InitialPreviewMVC.Models.HomeViewModel
@{
ViewBag.Title = "Home Page";
}
<script>
$("#Image1").fileinput({
uploadUrl: "@Url.Action("upload", "Home")",
uploadAsync: false,
minFileCount: 2,
maxFileCount: 5,
overwriteInitial: false,
initialPreview: [
@* Aqui using string.Join para montar os itens do array, tem um milhão de formas de fazer isso! *@
@Html.Raw(string.Join(",\r\n ",
Model.PreviewImages.Select(img => "\"<img style='height:160px' src='" + img.Url + "'>\"")))
],
Again, the namespace of @model
will be another!
See that we no longer use a dynamic field like ViewBag
and we even have code completion suggestion when typing Model.
... You will see that the PreviewImages
property will appear.
Result
The markup generated for both solutions is equal and follows the part only of the <script>
itself:
<script>
$("#Image1").fileinput({
uploadUrl: "/Home/upload",
uploadAsync: false,
minFileCount: 2,
maxFileCount: 5,
overwriteInitial: false,
initialPreview: [
"<img style='height:160px' src='/Content/img/galeriaimagens/sl1.jpg'>",
"<img style='height:160px' src='/Content/img/galeriaimagens/sl2.jpg'>",
"<img style='height:160px' src='/Content/img/galeriaimagens/sl3.jpg'>"
],
initialPreviewConfig: [
{ caption: "Food-1.jpg", size: 329892, width: "120px", url: "/Home/remover", key: 1 },
{ caption: "Food-2.jpg", size: 872378, width: "120px", url: "/Home/remover", key: 2 },
{ caption: "Food-3.jpg", size: 632762, width: "120px", url: "/Home/remover", key: 3 },
{ caption: "Food-4.jpg", size: 632762, width: "120px", url: "/Home/remover", key: 4 },
],
uploadExtraData: {
img_key: "1000",
img_keywords: "happy, nature",
}
});
</script>