Upload multiple files / access input id at server site - asp.net-mvc-2

I am trying to upload a couple of files. The upload itself works well for a single upload but I can't figure out how to access the element name to make sure each upload is assigned to the correct field. HttpPostedFileBase doesn't seem to contain that type of info anymore.
public ActionResult Edit(int id, FormCollection collection) {
Report report = re.GetReport(id);
var fileNames = new List<string>();
foreach (string file in Request.Files) {
var postedFile = Request.Files[file] as HttpPostedFileBase;
if (postedFile.ContentLength == 0)
continue;
fileNames.Add(UploadFile(basedir, postedFile));
}
// Rather than guessing which is which I'd like to get the field name or id.
report.Image = fileNames[0];
report.File = fileNames[1];
UpdateModel(report, "report");
rep.Save();
In the view I have
<%: Html.LabelFor(model => model.report.Image)%>
<input id="report_Image" type="file" name="Image" />
<%: Html.LabelFor(model => model.report.File)%>
<input id="report_Image" type="file" name="File" />
Thanks,
Duffy

var fileNames = new List<string>();
foreach (string file in Request.Files) {
var postedFile = Request.Files[file] as HttpPostedFileBase;
if (postedFile.ContentLength == 0)
continue;
fileNames.Add(UploadFile(basedir,postedFile));
}
The variable file in the foreach contain the name of your input field. So its value will be Image and File Respectively. I checked it in MVC2
So you can do like this
var fileNames = new Dictionary<string,string>();
foreach (string file in Request.Files)
{
var postedFile = Request.Files[file] as HttpPostedFileBase;
if (postedFile.ContentLength == 0)
continue;
fileNames.Add(file,UploadFile(basedir,postedFile));
}
//Now you have added the values with key so you can use the
//input field name to access them
report.Image = fileNames["Image"];
report.File = fileNames["File"];

Phil Haack blogged about this recently, maybe his example will help.
You could also look at the extension of the file to determine which file it is.
Can you use Request.Files["File"] and Request.Files["Image"]?

I use uploadify in my MVC apps. It's free and a great solution for uploading multiple files.
http://www.uploadify.com/
http://trycatchfail.com/blog/post/2009/05/13/ASPNET-MVC-HtmlHelper-for-Uploadify-Take-One.aspx

Related

Insert HTML in docx file

I have made an application that fills wordfiles with customxmlparts now I am trying to put text into a textfield, but it has HTML in it and I want it to show the styling of it. I tried converting it to rich text format but that just gets pasted in the word file. Here is an example of the code:
var taskId = Guid.NewGuid();
var tempFilePath = $"{Path.GetTempPath()}/{taskId}";
using (var templateStream = new FileStream($"{tempFilePath}.docx", FileMode.CreateNew))
{
templateStream.Write(template, 0, template.Length);
// 1. Fill template.
using (WordprocessingDocument doc = WordprocessingDocument.Open(templateStream, true))
{
MainDocumentPart mainDocument = doc.MainDocumentPart;
if (mainDocument.CustomXmlParts != null)
{
mainDocument.DeleteParts<CustomXmlPart>(mainDocument.CustomXmlParts);
}
CustomXmlPart cxp = mainDocument.AddCustomXmlPart(CustomXmlPartType.CustomXml);
foreach (var line in data.Lines)
{
if (line.MoreInfo != null && line.MoreInfo != " ") {
}
}
var xmlData = ObjectToXml(data);
using (var stream = GenerateStreamFromString(tempFilePath, xmlData))
{
cxp.FeedData(stream);
}
mainDocument.Document.Save();
}
}
You can't just write the HTML formatted text into a DOCX field, you would need to convert it into a WordprocessingML format.
However, there is another way that you could try and that is to insert an "AltChunk" element. That element represents a sort of like a placeholder which can reference a HTML file and then when the DOCX file is opened in MS Word, it will make that HTML to WordprocessingML conversion for you. For details see: How to Use altChunk for Document Assembly
Alternatively you could use some third party, like GemBox.Document, which can make that HTML to WordprocessingML conversion for you.
For example check this Set Content example:
// Set content using HTML tags
document.Sections[0].Blocks[4].Content.LoadText(
"Paragraph 5 <b>(part of this paragraph is bold)</b>", LoadOptions.HtmlDefault);

Codefluent Potentially dangerous Request.Form value with richtext fields

After adding the multivalue (flags) enumeration solution (which works very well, thank you) from
http://blog.codefluententities.com/tag/multi-enumeration-values/
to our MVC project we are now getting the dreaded "Potentially dangerous Request.Form value" on richtext fields across the board that we're using to generate html with a wysiwyg editor (summernote in this case).
If I remove summernote and just submit plain text the fields work perfectly, however putting any html code into the text input generates the error.
Fortunately, the error is coming out of the code just added (above) for the multi-enumeration on line 246:
Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (Description="...rem ipsum <strong>dolor</stron...").
Source Error:
Line 244: continue;
Line 245:
Line 246: Add(name, nvc[name]);
Line 247:
Line 248: }
EDIT:
For clarity, here is the whole method in question:
private void AddRange(NameValueCollection nvc)
{
foreach (string name in nvc)
{
// handle MultiSelectList templates
const string listSelectedToken = ".list.item.Selected";
const string listValueToken = ".list.item.Value";
if (name.EndsWith(listSelectedToken))
{
List<bool> bools = CodeFluent.Runtime.Utilities.ConvertUtilities.SplitToList<bool>(nvc[name], ',');
string propertyName = name.Substring(0, name.Length - listSelectedToken.Length);
string valueKey = propertyName + listValueToken;
List<string> keys = CodeFluent.Runtime.Utilities.ConvertUtilities.SplitToList<string>(nvc[valueKey], ',');
int j = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < keys.Count; i++)
{
if (bools[j])
{
if (sb.Length > 0)
{
sb.Append(CodeFluentConfiguration.EntityKeyListSeparator);
}
sb.Append(keys[i]);
j++;
}
j++;
}
Add(propertyName, sb.ToString());
continue;
}
if (name.EndsWith(listValueToken))
continue;
Add(name, nvc[name]);
}
}
Have I missed something in the multi-value implementation?
Thanks,
Russ
I don't think this error is related to the use of a multi-valued enumeration. In fact you post a value for the Description field that contains HTML tags (strong). By default ASP.NET prevents this and throw a validation exception.
If you expect your users to enter HTML, you must instruct ASP.NET to authorize HTML.
Change the EntityValueProvider
AddRange(context.HttpContext.Request.Unvalidated.Form); // Add Unvalidated
AddRange(context.HttpContext.Request.Unvalidated.QueryString);
Or use the web.config: validateRequest or requestValidationMode
<system.web>
<pages validateRequest="false" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
Use AllowHtmlAttribute
public class Sample
{
[AllowHtml]
public string Description {get;set;}
}
Or ValidateInputAttribute
[HttpPost, ValidateInput(true, Exclude = "Description")]
public ActionResult Edit(int id, FormCollection collection)
{
...
}

jsTree customize <li> using the alternative JSON format along with AJAX

I am using the alternative JSON format along with AJAX to load data in tree. Now there is a new ask, I am required to add a new element at the end of <li> tag.
I have created sample URL to display what I am currently doing.
Tree crated using alternative JSON format along with AJAX
And how the new LI should appear
Tree created using hard coded HTML but shows how the LI should look like
I think I should be able to do this if I use HTML Data but since the project is already live with JSON format this would require me to change a lot so before I start making this major change I just wanted to check if this is possible using JSON and AJAX format or not.
So I got answer from Ivan - Answer
In short there is misc.js in the src folder which has question mark plugin, this is the best example of what I wanted to do.
I tweaked its code for my needs and here is the new code.
(function ($, undefined) {
"use strict";
var span = document.createElement('span');
span.className = 'glyphicons glyphicons-comments flip jstree-comment'
$.jstree.defaults.commenticon = $.noop;
$.jstree.plugins.commenticon = function (options, parent) {
this.bind = function () {
parent.bind.call(this);
};
this.teardown = function () {
if (this.settings.commenticon) {
this.element.find(".jstree-comment").remove();
}
parent.teardown.call(this);
};
this.redraw_node = function (obj, deep, callback, force_draw) {
var addCommentIcon = true;
var data = this.get_node(obj).data;
//....Code for deciding whether comment icon is needed or not based on "data"
var li = parent.redraw_node.call(this, obj, deep, callback, force_draw);
if (li && addCommentIcon) {
var tmp = span.cloneNode(true);
tmp.id = li.id + "_commenticon";
var $a = $("a", li);
$a.append(tmp);
}
return li;
};
};
})(jQuery);

Send Email fields not rendering in Sitecore Web Forms For Marketers

I have an issue with the WFFM Send Email Message save action (Sitecore 6.5.0). I'm trying to send an email that includes the form placeholders from the "Insert Field" dropdown in the Send Email editor. Sometimes the fields will render correctly, but most times the email will include the placeholder text instead of the field's actual value.
For example, this is the email that is coming through:
First Name: [First Name]
Last Name: [Last Name]
Email: [Email Address]
Company Name: [Company Name]
Phone Number: [Phone Number]
I think it has to do with the Send Email editor using a rich text editor for the email template, but I've tried adjusting the message's HTML to no avail. This is what the markup looks like: (the <p> tags and labels used to be inline, but that didn't work either)
<p>First Name:
[<label id="{F49F9E49-626F-44DC-8921-023EE6D7948E}">First Name</label>]
</p>
<p>Last Name:
[<label id="{9CE3D48C-59A0-432F-B6F1-3AFD03687C94}">Last Name</label>]
</p>
<p>Email:
[<label id="{E382A37E-9DF5-4AFE-8780-17169E687805}">Email Address</label>]
</p>
<p>Company Name:
[<label id="{9C08AC2A-4128-47F8-A998-12309B381CCD}">Company Name</label>]
</p>
<p>Phone Number:
[<label id="{4B0C5FAC-A08A-4EF2-AD3E-2B7FDF25AFA7}">Phone Number</label>]
</p>
Does anyone know what could be going wrong?
I have encountered this issue before, but was using a custom email action. I managed to fix it by not using the deprecated methods in the SendMail class and instead using the
Sitecore.Form.Core.Pipelines.ProcessMessage namespace's ProcessMessage and ProcessMessageArgs classes.
My use case was a little more complicated than yours, as we were also attaching a PDF brochure to our message (which is why we were using the custom email action in the first place), but here is the code:
public class SendBrochureEmail : SendMail, ISaveAction, ISubmit
{
public new void Execute(ID formId, AdaptedResultList fields, params object[] data)
{
try
{
var formData = new NameValueCollection();
foreach (AdaptedControlResult acr in fields)
{
formData[acr.FieldName] = acr.Value;
}
var senderName = formData["Your Name"];
var emailTo = formData["Recipient Email"];
var recipientName = formData["Recipient Name"];
var documentTitle = formData["Document Title"];
if (documentTitle.IsNullOrEmpty())
{
documentTitle = String.Format("Documents_{0}", DateTime.Now.ToString("MMddyyyy"));
}
Subject = documentTitle;
if (!String.IsNullOrEmpty(emailTo))
{
BaseSession.FromName = senderName;
BaseSession.CatalogTitle = documentTitle;
BaseSession.ToName = recipientName;
var tempUploadPath = Sitecore.Configuration.Settings.GetSetting("TempPdfUploadPath");
var strPdfFilePath =
HttpContext.Current.Server.MapPath(tempUploadPath + Guid.NewGuid().ToString() + ".pdf");
//initialize object to hold WFFM mail/message arguments
var msgArgs = new ProcessMessageArgs(formId, fields, MessageType.Email);
var theDoc = PdfDocumentGenerator.BuildPdfDoc();
theDoc.Save(strPdfFilePath);
theDoc.Clear();
FileInfo fi = null;
FileStream stream = null;
if (File.Exists(strPdfFilePath))
{
fi = new FileInfo(strPdfFilePath);
stream = fi.OpenRead();
//attach the file with the name specified by the user
msgArgs.Attachments.Add(new Attachment(stream, documentTitle + ".pdf", "application/pdf"));
}
//get the email's "from" address setting
var fromEmail = String.Empty;
var fromEmailNode = Sitecore.Configuration.Factory.GetConfigNode(".//sc.variable[#name='fromEmail']");
if (fromEmailNode != null && fromEmailNode.Attributes != null)
{
fromEmail = fromEmailNode.Attributes["value"].Value;
}
//the body of the email, as configured in the "Edit" pane for the Save Action, in Sitecore
msgArgs.Mail.Append(base.Mail);
//The from address, with the sender's name (specified by the user) in the meta
msgArgs.From = senderName + "<" + fromEmail + ">";
msgArgs.Recipient = recipientName;
msgArgs.To.Append(emailTo);
msgArgs.Subject.Append(Subject);
msgArgs.Host = Sitecore.Configuration.Settings.MailServer;
msgArgs.Port = Sitecore.Configuration.Settings.MailServerPort;
msgArgs.IsBodyHtml = true;
//initialize the message using WFFM's built-in methods
var msg = new ProcessMessage();
msg.AddAttachments(msgArgs);
msg.BuildToFromRecipient(msgArgs);
//change links to be absolute instead of relative
msg.ExpandLinks(msgArgs);
msg.AddHostToItemLink(msgArgs);
msg.AddHostToMediaItem(msgArgs);
//replace the field tokens in the email body with the user-specified values
msg.ExpandTokens(msgArgs);
msg.SendEmail(msgArgs);
//no longer need the file or the stream - safe to close stream and delete delete it
if (fi != null && stream != null)
{
stream.Close();
fi.Delete();
}
}
else
{
Log.Error("Email To is empty", this);
throw new Exception("Email To is empty");
}
}
catch (Exception ex)
{
Log.Error("Test Failed.", ex, (object) ex);
throw;
}
finally
{
BrochureItems.BrochureItemIds = null;
}
}
public void Submit(ID formid, AdaptedResultList fields)
{
Execute(formid, fields);
}
public void OnLoad(bool isPostback, RenderFormArgs args)
{
}
}
It is very possible that the Email Action that WFFM ships with is using the deprecated methods, which could be your problem. I do not have time to look into it, but you can decompile the DLL and look to see what their Email Action is doing. Regardless, the above code should work out of the box, save for updating the fields to those that you are using and removing the code for attaching the PDF, should you choose to not have attachments.
Good luck, and happy coding :)
If you change a field on the form in any way (caption, name, type, etc) the link will change and you need to re-insert the placeholder and move it up to its location in your expected email. This is also true if you duplicate a form. You'll have to reinsert all the fields in the email or you will just get the outcome you show above.
Reinserting upon a change will ensure the value is collected!

Fill in some from HTML form slots using link from another page?

I have a fairly vanilla HTML page with an (inquiry) form. That form has topic field. I'd like to be able to link to that page from another topic-specific page (using an A tag?) on the website, causing that topic field (and maybe some subset of other fields) to be filled in automatically.
Suggestions?
Add a custom param (topic name) to the page where the link points and use it as a subject/topic field.
like:
link
Then, on a target page (with inquiry) use this javascript:
<script type="text/javascript">
// Read a page's GET URL variables and return them as an associative array.
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
var params = getUrlVars();
document.getElementById('your_topic_field_id').value = params['topic_title'];
</script>