Apex:outputfield not outputting anything on VisualForce Page - apex-code

I am trying to create a pdf from the Lead Object in Salesforce using the Apex language. I am able to create the pdf and attach it to the Current Lead but it does not pull in any of the information from the Lead into the PDF itself.
Page Code:
<apex:page standardController="Lead" renderAs="pdf" showHeader="false">
<apex:stylesheet value="{!$Resource.pdfCss}"/>
<apex:panelGrid columns="1" width="100%">
<apex:outputText value="{!Lead.Name}" styleClass="companyName"/>
<apex:outputText value="{!NOW()}"></apex:outputText>
</apex:panelGrid>
</apex:page>
Class Code:
public class attachPDFToLead {
private final Lead a; //Lead object
//constructor
public attachPDFToLead(ApexPages.StandardController standardPageController) {
a = (Lead)standardPageController.getRecord();
}
public PageReference attachPDF() {
PageReference pdfPage = Page.PDF;
Blob pdfBlob = pdfPage.getContent();
Attachment attach = new Attachment(parentId = a.Id, Name = 'insuranceVerification.pdf', body = pdfBlob);
insert attach;
PageReference pageURL = new ApexPages.StandardController(a).view();
pageURL.setRedirect(true);
return pageURL;
}
}
Button Setup:
Button Setup

Related

MVC6 TagHelpers with disposable

In the older MVC HTML Helpers, one could use IDisposable to wrap content - for example the BeginForm helper would automatically wrap *stuff* with a closing form tag
<% using (Html.BeginForm()) {%>
*stuff*
<% } %>
Is this wrapping of content supported with MVC6 TagHelpers?
For example I would like this
<widget-box title="My Title">Yay for content!</widget-box>
to be expanded into a bootstrap widget-box with wrapping divs:
<div class="widget-box">
<div class="widget-header">
<h4 class="widget-title">My Title</h4>
</div>
<div class="widget-body">
<div class="widget-main">
Yay for content!
</div>
</div>
</div>
Is this possible with TagHelpers?
Solution: I have baked #DanielJG's answer into a working demo on github which consumes WidgetBoxTagHelper.cs (will stay current with Beta/RC/RTM as am using the lib in my production app)
Tag helpers have to implement the interface ITagHelper (as pointed by #NTaylorMullen, the TagHelper class is just a convenience class you can use when implementing it) which forces you to use the methods Process and ProcessAsync, so you cannot rely on adding contents in a Dispose method.
However you have full control over the output content so you can replace/modify it as you need. For example, a quick approximation to your widget tag helper (Using the 1.0 version of the framework):
[HtmlTargetElement("widget-box")]
public class WidgetTagHelper : TagHelper
{
public string Title { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var outerTag = new TagBuilder("div");
outerTag.Attributes.Add("class", output.TagName);
output.MergeAttributes(outerTag);
output.TagName = outerTag.TagName;
//Create the header
var header = new TagBuilder("div");
header.Attributes.Add("class", "widget-header");
header.InnerHtml.Append(this.Title);
output.PreContent.SetHtmlContent(header);
//Create the body and replace original tag helper content
var body = new TagBuilder("div");
body.Attributes.Add("class", "widget-body");
var originalContents = await output.GetChildContentAsync();
body.InnerHtml.Append(originalContents.GetContent());
output.Content.SetHtmlContent(body);
}
}
In your razor you will have:
<widget-box title="My Title">Yay for content!</widget-box>
Which will be rendered as:
<div class="widget-box">
<div class="widget-header">My Title</div>
<div class="widget-body">Yay for content!</div>
</div>
DonĀ“t forget to register the tag helpers in your assembly by adding a #addTagHelper directive to the _ViewImports.cshtml file. For example this will register all helpers in my application:
#addTagHelper *, WebApplication2
OLD beta7 code
In beta7 you had to use the [TargetElement] attribute.
The TagBuilder class had a SetInnerText method you could use to set its context as text.
The code looked like:
[TargetElement("widget-box")]
public class WidgetTagHelper : TagHelper
{
private IHtmlEncoder encoder;
public WidgetTagHelper(IHtmlEncoder encoder)
{
this.encoder = encoder;
}
public string Title { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var outerTag = new TagBuilder("div");
outerTag.Attributes.Add("class", output.TagName);
output.MergeAttributes(outerTag);
output.TagName = outerTag.TagName;
//Create the header
var header = new TagBuilder("div");
header.Attributes.Add("class", "widget-header");
header.SetInnerText(this.Title);
output.PreContent.SetContent(header);
//Create the body and replace original tag helper content
var body = new TagBuilder("div");
body.Attributes.Add("class", "widget-body");
var originalContents = await context.GetChildContentAsync();
using (var writer = new StringWriter())
{
body.TagRenderMode = TagRenderMode.StartTag;
body.WriteTo(writer, encoder);
originalContents.WriteTo(writer, encoder);
body.TagRenderMode = TagRenderMode.EndTag;
body.WriteTo(writer, encoder);
output.Content.SetContent(writer.ToString());
}
}
}
OLD beta5 code
There was an InnerHtml property in the tag helpers.
There was a ToHtmlString method in the tag helpers used to render them as html.
The code looked like:
[TargetElement("widget-box")]
public class WidgetTagHelper: TagHelper
{
public string Title { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var outerTag = new TagBuilder("div");
outerTag.Attributes.Add("class", output.TagName);
output.MergeAttributes(outerTag);
output.TagName = outerTag.TagName;
//Create the header
var header = new TagBuilder("div");
header.Attributes.Add("class", "widget-header");
header.InnerHtml = this.Title;
output.PreContent.SetContent(header.ToHtmlString(TagRenderMode.Normal).ToString());
//Create the body and replace original tag helper content
var body = new TagBuilder("div");
body.Attributes.Add("class", "widget-body");
var originalContents = await context.GetChildContentAsync();
body.InnerHtml = originalContents.GetContent();
output.Content.SetContent(body.ToHtmlString(TagRenderMode.Normal).ToString());
}
}

Unable to read View Bag value from controller to view

I have created a view bag in controller's post back event which stores the image path.
Then,i used this view bag value in image src attribute.But image is not displayed.
Model:
public class FileManagement
{
public string FileName { get; set; }
public string Path { get; set; }
}
Code for uploading image
[HttpPost]
public ActionResult UploadPic(FileManagement fmanage, HttpPostedFileBase file)
{
string email = User.Identity.Name;
if (file != null && file.ContentLength > 0)
{
var FileName = string.Format("{0}.{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
var path = Path.Combine(Server.MapPath("~/Content/Uploads"), FileName);
file.SaveAs(path);
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
var query = from q in Session.Query<Registration>() where q.Email == email select q;
if (query.Count() > 0)
{
foreach (var updated in query)
{
updated.FileName = FileName;
updated.Path = path;
session.SaveChanges();
}
}
}
}
else ModelState.AddModelError("", "Remove the errors and try again");
return View();
}
Controller
[HttpGet]
public ActionResult DisplayPic()
{
ViewBag.Imagepath = "C:\\Users\\Wasfa\\Documents\\Visual Studio 2012\\Projects\\MvcMembership\\MvcMembership\\App_Data\\Uploads\\annonymous.jpg";
return View();
}
[HttpPost]
public ActionResult DisplayPic(FileManagement fm)
{
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
string ipath;
// string UserName = User.Identity.Name;
string UserName = "wasfa_anjum#yahoo.com";
var getPath = from p in Session.Query<Registration>()
where p.Email == UserName
select p;
if (getPath.Count() > 0)
{
foreach (var imgpath in getPath)
{
ipath = imgpath.Path;
ViewBag.Imagepath = ipath;
}
}
}
return View();
}
View:
#using (Html.BeginForm())
{
<div>
<img src="#Url.Content(ViewBag.Imagepath)" width="200" height="200" />
</div>
<input type="submit" value="Display" />
}
In my opinion, your problem is not to do with ASP.NET MVC, but you are missing some HTML/Web basics.
You have to understand that when you want to access a resource (html file, image etc), you have to use the HTTP URI syntax. You cannot and should not use your Windows file system path syntax.
Using something like C:\\Users\\Wasfa\\Documents\\Visual Studio 2012\\Projects\\MvcMembership\\MvcMembership\\App_Data\\Uploads\\annonymous.jpg" in HTML is completely wrong. To understand it better, imagine when you have your ASP.NET MVC website up and running for its users to access, they will come to you web page and the HTML downloaded on their browser will be:
<img src="C:\Users\Wasfa\Documents\Visual Studio 2012\Projects\MvcMembership\MvcMembership\App_Data\Uploads\annonymous.jpg" />
Do you think that path will exist on their computers? No.
So, to instruct the <img /> tag to fetch the image from the server, you have to specify either a full HTTP URI, for example:
<img src="http://mywebsite.com/Content/Uploads/annonymous.jpg" />
or a relative HTTP URI (which is like a relative path from your web site's root folder):
<img src="~/Content/Uploads/annonymous.jpg" />
Another problem with your approach is that App_Data is a special folder and its contents are not accessible from the browser by default. So, as per ASP.NET MVC convention, you can create a Content folder in your project to hold your static images and other static content like style sheels, and then link to them.
Once you do that, no one stops you from providing the relative path for your default image as a ViewBag property.
ViewBag.Imagepath = "~/Content/Uploads/annonymous.jpg";
And then use it the way you want:
<img src="#Url.Content(ViewBag.Imagepath)" width="200" height="200" />
I also expect the paths you subsequently fetch from the database, also follow this scheme.
path for image must have forward slash (/),
more over this type of path might work only in your local system and not in your server.
Try using Server.MapPath to fetch your path
Using ViewBag for displaying image is a bad idea, consider using your model property to store the image path and use
<img src="#Url.Content(Model.ImagePath)" alt = "Image" />
EDIT :
Controller:
[HttpGet]
public ActionResult DisplayPic()
{
FileManagement fm = new FileManagement();
fm.Path = "Your image path";
return View(fm);
}
View :
`<img src="#Url.Content(Model.path)" alt = "Image" />`
didn't check the code, but this should work.
It looks like you only really need one result for getPath, this might clean your code up a bit
var imgPath= Session.Query<Registration>()
.FirstOrDefault(p => p.Email == UserName)
.Select(i => i.Path);
if (!string.IsNullOrEmpty(imgPath)
ViewBag.Imagepath = imgPath;
else
{
//no user found, handle error
}
Other than that your code looks fine, can you debug through your application and see what imgPath is equal to after your query is run?
In case, if the image to be displayed when export to excel from the web page.
Use the server path of the image, otherwise, the image would not be loaded from the assembly image folder.
Example:
config:
<add key="LogoPath" value="http:\\mysite\\images\\" />
code:
companyLogo = string.Format("{0}myLogo.png", System.Web.Configuration.WebConfigurationManager.AppSettings["LogoPath"]);
HTML:
<img src='" + #Url.Content(companyLogo) + "' />

Updating only the partial view contained in a mvc 3 page?

I have a MVC 3 page that returns a list of user responses with a partial view called "memo" (which displays/add memos) for each response. When I add a memo to a response, it should update the db and the list of memos for that response. It should be partial page update via ajax, which effects only the partial view "memo".
The view Response.chtml that contains "memo":
#using (Html.BeginForm("Response", "User", FormMethod.Post, new { id = "UserResponse" }))
{
.... code removed ....
#foreach (var response in Model)
{
<div class="qna"><input type="text" id=#response.responseId value="#response.ResponseText" />
<div>#Html.Partial("_memo", response.responseId)</div>
}
.....
The partial page "_memo.chtml":
<div>add memo</div>
<ul id="memos">
#foreach (var memo in Model) {
<li>#memo.Text</li>
}
</ul>
<form method="post" id="memoForm"
action="#Url.Action("AddMemo")">
#Html.TextArea("Memo", new { rows = 5, cols = 50 })
<br />
<input type="submit" value="Add" />
</form>
Controller for view User/Response:
[HttpGet]
public ActionResult Response(id)
{
.....
return View(responses);
I just started with the code above, need help filling the blanks.
If I pass the response Id to the partial view, how do I pull the list of memos for that response? Will it involve ajax? (instead of ..Partial("_memo", response.memos))
How do I update the partial view via ajax call. What is ajax call (sample code) on the client side and how would the controller look? When the ajax call is successful, how do I update the list memos div="memos" to reflect the new memo?
Will the form action from Response conflict with form action of the partial view Memo?
Answers to Questions:
You shouldn't pass the responseId to the partial, you should pass the memo collection from your response object and make your partial view strongly typed to that collection.
See full code example below.
You don't need the form in the partial since you're making a simple ajax call to add the new memo. See full code example below.
This is a modified example from a project I am currently working on:
There is a bit of code to follow, so here goes:
This is my model. There are several sections on a career planning form, one of which is a section to select and update competencies. The SelectCompetencies model has a collection of competencies within it. The user will have the ability to add competencies. When they do, it will be added to the database and will update the list of competencies in the partial.
public class CareerPlanningFormViewModel
{
// code removed ...
public SelectCompetenciesModel SelectCompetencies { get; set; }
// code removed ...
}
public class SelectCompetenciesModel
{
public int CareerPlanningFormID { get; set; }
public IList<CompetencyModel> Competencies { get; set; }
public byte MaximumCompetenciesAllowed { get; set; }
}
public class CompetencyModel
{
public int CompetencyID { get; set; }
public int? CompetencyOptionID { get; set; }
public string ActionPlan { get; set; }
public IDictionary<int, string> CompetencyOptions { get; set; }
}
The main view of the career planning form: /Views/CPF/CareerPlanningForm.cshtml
#model MyNamespace.Models.CareerPlanningForm.CareerPlanningFormViewModel
<link rel="stylesheet" href="#Url.Content("~/Content/CreateCPF.css")" />
#using (Html.BeginForm())
{
// other sections loaded here...
// code removed for brevity...
#Html.Partial("SelectCompetencies", Model.SelectCompetencies)
// other sections loaded here...
// code removed for brevity...
}
The SelectCompetencies partial: /Views/CPF/SelectCompetencies.cshtml
The user will fill in the new action plan text and click the add competency button.
That will post via ajax to CPFController/NewCompetencyTemplate
#model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesModel
#Html.HiddenFor(m => m.CareerPlanningFormID)
<h3>Select Competencies</h3>
<p class="guidance">
Select up to #Model.MaximumCompetenciesAllowed competencies to focus on improving.
</p>
<table id="CompetenciesTable">
<thead>
<tr>
<th>Competency</th>
<th>Action Plan:</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Competencies.Count(); i++)
{
#Html.EditorFor(m => m.Competencies[i])
}
</tbody>
<tfoot id="CompetenciesTableFooter" class="#(Model.Competencies.Count() < Model.MaximumCompetenciesAllowed ? "" : "hidden")">
<tr>
<td colspan="2">
#Html.TextArea("NewActionPlanText")
#Html.Button(ButtonType.Button, "Add Another Competency", "add", new { id = "AddCompetencyButton" })
</td>
</tr>
</tfoot>
</table>
#section script
{
<script>
jQuery(document).ready(function ($) {
var competenciesTableBody = $('#CompetenciesTable tbody'),
competenciesTableFooter = $('#CompetenciesTableFooter'),
addCompetencyButton = $('#AddCompetencyButton'),
newCompetencyTemplateUrl = '#Url.Content("~/CPF/NewCompetencyTemplate")',
count = competenciesTableBody.find('tr').length,
newActionPlanText = $('#NewActionPlanText'),
careerPlanningFormID = $('#CareerPlanningFormID');
addCompetencyButton.click(function () {
$.ajax({
url: newCompetencyTemplateUrl(),
type: 'POST',
data: {
careerPlanningFormID: careerPlanningFormID,
actionPlan: newActionPlanText,
itemCount: count
},
dataType: 'html',
success: function (data) {
var elements = $(data);
// other code removed here...
competenciesTableBody.append(elements);
// other code removed here...
}
});
});
});
</script>
}
Views/CPF/EditorTemplates/CompetencyModel.cshtml
#model MyNamespace.Models.CareerPlanningForm.CompetencyModel
<tr class="competency">
<td>
#Html.DropDownListFor(m => m.CompetencyOptionID, new SelectList(Model.CompetencyOptions, "Key", "Value"), "Select competency...")
</td>
<td>
#Html.TextAreaFor(m => m.ActionPlan, new { #class = "competencyActionPlan" })
#Html.HiddenFor(m => m.CompetencyID)
</td>
</tr>
The controller containing the action to add the new competency: /Controllers/CPFController.cs
This will call the CareerPlanningFormService to add the new competency and will return a partial view for NewCompetencyTemplate that will render out the new competency
public class CPFController : Controller
{
private readonly ICareerPlanningFormService careerPlanningFormService;
public CPFController(ICareerPlanningFormService careerPlanningFormService)
{
this.careerPlanningFormService = careerPlanningFormService;
}
[HttpPost]
public PartialViewResult NewCompetencyTemplate(int careerPlanningFormID, int itemCount, string newActionPlanText)
{
var count = itemCount + 1;
// Even though we're only rendering a single item template, we use a list
// to trick MVC into generating fields with correctly indexed name attributes
// i.e. Competencies[1].ActionPlan
var model = new SelectCompetenciesModel
{
Competencies = Enumerable.Repeat<CompetencyModel>(null, count).ToList()
};
model.Competencies[count - 1] = this.careerPlanningFormService.BuildNewCompetencyModel(careerPlanningFormID, newActionPlanText);
return this.PartialView(model);
}
}
My service class: CareerPlanningFormService.cs
This handles the business logic and makes the calls to the repository to add the item to the database and returns a new CompetencyModel
public class CareerPlanningFormService : ICareerPlanningFormService
{
private readonly IMyRenamedRepository repository;
private readonly IPrincipal currentUser;
public CareerPlanningFormService(
IMyRenamedRepository repository,
IPrincipal currentUser)
{
this.repository = repository;
this.currentUser = currentUser;
}
public CompetencyModel BuildNewCompetencyModel(int careerPlanningFormID, string newActionPlanText)
{
var competency = new Competency
{
CareerPlanningFormID = careerPlanningFormID,
CompetencyOptionID = null,
ActionPlan = newActionPlanText
};
this.repository.Add(competency);
this.repository.Commit();
return new CompetencyModel
{
CompetencyID = competency.CompetencyID,
CompetencyOptionID = competency.CompetencyOptionID,
ActionPlan = competency.ActionPlan,
CompetencyOptions = this.GetCompetencyOptionsForCareerPlanningFormID(careerPlanningFormID)
};
}
}
Now, the partial for NewCompetencyTemplate: Views/CPF/NewCompetencyTemplate.cshtml
This is very simple, it simply renders the same editor template as above, for the last competency in the collection (which we just added)
#model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesViewModel
#Html.EditorFor(m => m.Competencies[Model.Competencies.Count() - 1])
When the ajax call succeeds, it will receive this partial back from the controller action method it called. It then takes the partial and appends it to the competencies table body
// snippet from ajax call above
competenciesTableBody.append(elements);
I hope this helps. Let me know if you have any additional questions.
While you're correct that you can do it just by returning a partial view containing the updated content, you may also consider using jQuery's load method.
Look here, in particular at the "loading page fragments" section. Basically you can just get the original page again and jQuery will "extract" the content you want as long as it can be targetted by a selector (such as a div id).
Note, this solution is not suitable in all cases as there will be redundant markup in the response from the server because you will be discarding the rest of the page content and just using the updated part.

Displaying an uploaded image in MVC 3 Razor

Well, this newbie is doing something wrong when displaying images uploaded to the server:
model:
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
}
controller (upload - called by the [HttpPost] public ActionResult Create):
public void Upload(Person person)
{
var image = WebImage.GetImageFromRequest();
var filename = Path.GetFileName(image.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads/Fotos"), filename);
image.Save(path);
person.ImageUrl = Url.Content(Path.Combine("~/App_Data/Uploads/Fotos", filename));
}
create view:
...
#using (Html.BeginForm("Create", "Person", FormMethod.Post, new { #encType = "multipart/form-data" }))
{
...
#FileUpload.GetHtml(initialNumberOfFiles: 1, allowMoreFilesToBeAdded: false, includeFormTag: false, uploadText: "image")
...
<div>
<input type="submit" value="Create" /> |
#Html.ActionLink("Back", "Index")
</div>
}
So far, so good, the image is uploaded to the folder and the url is saved
Now, I want to see it in the Detail View
detail view:
<div class="display-foto">
<img src="#Url.Content(Server.MapPath(Model.ImageUrl))" alt="IMAGE" />
</div>
Viewing the generated code, everything seems to be alright:
<img src="D:\Users\x\Documents\Visual Studio 2010\Projects\CMI_AD\CMI_AD\App_Data\Uploads\Fotos\_nofoto.jpg" alt="IMAGE" />
But the fact is that nothing appears on the screen except the text "IMAGE".
What am I doing wrong?
P.S. I've tried without the Server.MapPath, using the relative address "~\App_Data\Uploads\Fotos_nofoto.jpg" and the result is the same.
--- EDIT ---
#kmcc049: I've tried your suggestion creating a helper
public static class MyHelpers
{
public static IHtmlString MyImage(this HtmlHelper htmlHelper, string url)
{
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var img = new TagBuilder("img");
img.Attributes["alt"] = "[IMAGE]";
img.Attributes["src"] = UrlHelper.GenerateContentUrl(url, htmlHelper.ViewContext.HttpContext);
return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
}
}
the call in the view:
#Html.MyImage(Model.ImageUrl)
the generated code is
<img alt="[IMAGE]" src="/App_Data/Uploads/Fotos/_nofoto.jpg" />
but the result is the same: no image :(
--- SOLVED ---
Apparently the App_Data is not a good location to save uploaded files because accessing them will result an Error 403 - Forbidden. I move the files to ~/Uploads/Fotos and it works.
That's not a valid HTTP path. That's the path to the folder on your computer.
try the UrlHelper.GenerateContentUrl() method instead
http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.generatecontenturl.aspx

Mvc 3 Image Upload Gallery

I have implemented a file upload for images using ASP.NET Mvc 3 and the Microsoft.Web.Helpers NuGet package. The implementation is quit simple as it allows you to browse for a file and upload it to a specified directory.
Here is what I have for my image upload solution using ASP.NET MVC 3 and the Microsoft.Web.Helpers NuGet plugin.
Now the ViewModel code
namespace MvcImageUpload.Models {
public class ImageUploadViewModel {
[UIHint("UploadedImage")]
public string ImageUrl { get; set; }
public string ImageAltText { get; set; }
}
}
Now for the controller I've simply dropped this into the Home controller, since this is just a mock project to get it working. I just added an ActionResult which takes an ImageUploadViewModel as a parameter.
public ActionResult Upload(ImageUploadViewModel model) {
var image = WebImage.GetImageFromRequest();
if (image != null) {
if (image.Width > 500) {
image.Resize(500, ((500 * image.Height) / image.Width));
}
var filename = Path.GetFileName(image.FileName);
image.Save(Path.Combine("../Uploads/Images", filename));
filename = Path.Combine("~/Uploads/Images", filename);
model.ImageUrl = Url.Content(filename);
model.ImageAltText = image.FileName.Substring(0, image.FileName.Length - 4);
}
return View("Index", model);
}
My view for the uploading of images is simple, it has an Html.BeginForm, which handles the Post form method and has the encoding type set to be "multipart/form-data".
Then using The Microsoft.Web.Helpers.FileUpload helper, I request an image from the HTTP post and then display it using a custom DisplayFor template, called ImageViewer.
#model MvcImageUpload.Models.ImageUploadViewModel
#using Microsoft.Web.Helpers;
#{
ViewBag.Title = "Index";
}
<h2>Image Uploader</h2>
#using (Html.BeginForm("Upload", "Home", FormMethod.Post,
new { #encType = "multipart/form-data" })) {
#FileUpload.GetHtml(initialNumberOfFiles: 1, allowMoreFilesToBeAdded: false,
includeFormTag: false, addText: "Add Files", uploadText: "Upload File") <br />
<input type="submit" name="submit"
value="Upload Image" text="Upload Images"
style="font-size: .9em;" />
#Html.DisplayFor(x => x, "ImageViewer")<br />
}
Here is what the custom DisplayTemplate looks like
#model MvcImageUpload.Models.ImageUploadViewModel
#if (Model != null) {
<h4 style="color:Green;">Upload Success!</h4>
<p>
Alt Text has been set to <strong>#Model.ImageAltText</strong>
</p>
<img style="padding: 20px;"
src="#(String.IsNullOrEmpty(Model.ImageUrl) ? "" : Model.ImageUrl)"
id="uploadedImage" alt="#Model.ImageAltText"/>
}
This all works and the image gets successfully uploaded to the /Uploads/Images/FileName.extension on the form post.
My question
How can I now have another view to display all the images in that directory, paged and be able to select and delete and image, from the view and the directory?
Also I know the Microsoft.Web.Helpers.FileUpload, supports uploading of multiple files, but I can't find how to implement this with my current solution. Any help would be greatly appriceated.
After you click the Upload Image button, the system should call method which uses Request to get the file.
[HttpPost]
public ActionResult Upload()
{
if(Request.Files != null && Request.Files.Count > 0)
{
for (int i = 0; i < request.Files.Count; i++)
{
var postFile = request.Files[i];
if (postFile != null && postFile.ContentLength > 0)
{
if (postFile.ContentLength < GetMaxRequestLength()) //10MB
{
var file = new ContractAttachment
{
Name = Path.GetFileName(postFile.FileName),
ContentType = postFile.ContentType,
FileLength = postFile.ContentLength,
FileData = GetStreamBuffer(postFile)
};
files.Add(file);
}
}
}
}
}
Hope this help.
what you are asking about looks rather implementation to me then any query....
to Display:
Fetch all images from your Uploads/Images directory through DirectoryInfo... you can search a directory based on some extension and then it will give you a result set which you can iterate.....
Create a view that will display all records as Image links and in controller fetch the resultset to that View.... Bind those records as you want them to display in your VIEW...
System.IO.DirectoryInfo info = new System.IO.DirectoryInfo("your directory path");
var filesinfo= info.GetFiles("*.jpg", System.IO.SearchOption.AllDirectories);
var filenum= filesinfo.GetEnumerator();
while (filenum.MoveNext())
{
//populate some entity like in your case you have ImageUploadViewModel
}
and you can implement you delete logic using Ajax or through post back depends how you want it....
Asp.net MVC Views following this tutorial and it will let you go through this....
but again what you are asking is more like implementation Code not any issue....
The approach I've followed previously, is to persist the file information in a database(or whatever is appropriate). e.g. path, filename, content-type, filesize.
This gives you the most flexibility when editing (alt text, title, description, relation to other objects).
Downloading/Viewing the files can then be handled based on path convention, by creating a ViewImage controller which just gets an image id as parameter.
You can then build a url from the path to the file and you only need to set the content-type.
IIS then does the rest.

Resources