I have to display DLFileEntry records based on the expando value. I have followed the link https://www.liferay.com/community/wiki/-/wiki/Main/Search+for+objects+by+custom+attributes which I felt was clear enough.
When I implemented the same thing here...I get the 'no records availble'..
The primary key values I am getting from the loop are present in DLFileEntryMetadata but not in DLFileEntry table. So, the default message is getting displayed that no records are available.
<liferay-ui:search-container delta="5" emptyResultsMessage=
"no-records-available- for-employee" deltaConfigurable="true" >
<liferay-ui:search-container-results>
<%
long classNameId = ClassNameLocalServiceUtil.getClassNameId(DLFileEntry.class);
long companyId = PortalUtil.getDefaultCompanyId();
List<ExpandoValue> values = ExpandoValueLocalServiceUtil.getColumnValues(companyId,
classNameId, ExpandoTableConstants.DEFAULT_TABLE_NAME,
"employeeId",String.valueOf(employeeId), -1, -1);
out.println(values.isEmpty());
List<DLFileEntry> empFiles = new ArrayList<DLFileEntry>();
DLFileEntry fileEntry;
for (int i = 0; i < values.size(); i++) {
long fileId = values.get(i).getClassPK();
try{
out.println(userId);
fileEntry = DLAppLocalServiceUtil.getFileEntry(fileId);
empFiles.add(fileEntry);
}catch(Exception e ){
}
}
searchContainer.setResults(empFiles);
total = results.size();
pageContext.setAttribute("results", results);
pageContext.setAttribute("total", total);
%>
</liferay-ui:search-container-results>
<liferay-ui:search-container-row className="com.liferay.portlet.documentlibrary.model.DLFileEntry" modelVar="fileEntry" rowVar="curRow"
escapedModel="<%=true %>">
<liferay-ui:search-container-column-text orderable="true" name="Name"
property="name" />
<liferay-ui:search-container-column-text orderable="true" name="Extension"
property="extension"/>
<liferay-ui:search-container-column-text orderable="true" name="Mime Type"
property="mimeType"/>
<liferay-ui:search-container-column-text orderable="true" name="Title"
property="title"/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator/>
the id you get in line:
long fileId = values.get(i).getClassPK();
is not file id but file version id. Try to replace your line:
fileEntry = DLAppLocalServiceUtil.getFileEntry(fileId);
with following one:
fileEntry = DLAppLocalServiceUtil.getFileVersion(fileId).getFileEntry();
br, Pawel
Since FileEntry cannot be cast to DLFileEntry, it is better to get the fileEntryId from this line
long fileEntryId2 = DLAppLocalServiceUtil.getFileVersion(fileId).getFileEntryId();
Then
fileEntry = DLFileEntryLocalServiceUtil.getDLFileEntry(fileEntryId2);
Related
I'm having issues making an actual table in my excel file. The file is created and all the data is there, but when I open the file the table definition doesn't exist. I'm using this method to try and turn the data range into a table.
private static Table CreateTable(string tableRange, IEnumerable<string> headers)
{
var table = new Table {
Id = 1,
Name = "Table 1",
DisplayName = "Table 1",
Reference = tableRange,
TotalsRowShown = false,
HeaderRowFormatId = 0
};
table.AddNamespaceDeclaration("x", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
UInt32Value i = 1;
var columns = new TableColumns();
foreach (var header in headers) {
columns.Append(new TableColumn {
Id = i++,
Name = header
});
}
var style = new TableStyleInfo {
Name = "TableStyleMedium2",
ShowFirstColumn = false,
ShowLastColumn = false,
ShowRowStripes = true,
ShowColumnStripes = false
};
table.Append(new AutoFilter { Reference = tableRange });
table.Append(columns);
table.Append(style);
return table;
}
The tableRange variable is a simple excel range string, like "A1:D27". I'm trying to add it to the worksheet like so:
var tableDefinitionPart = worksheetPart.AddNewPart<TableDefinitionPart>();
tableDefinitionPart.Table = CreateTable(tableRange, headers);
I'm not getting any errors when I open the file.
If I open the file with the XML Productivity tool and click on the "x:table (Table)" part within the worksheet I see this:
<x:table xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="1" name="Table 1" displayName="Table 1" ref="A1:Z2" totalsRowShown="0" headerRowDxfId="0">
<x:autoFilter ref="A1:Z2" />
<x:tableColumns>
<x:tableColumn id="1" name="Lab Name" />
....
<x:tableColumn id="26" name="Description" />
</x:tableColumns>
<x:tableStyleInfo name="TableStyleMedium2" showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" />
</x:table>
So it seems like I'm putting something properly into the file. It's just not an actual "table" as far as Excel is concerned.
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)
{
...
}
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!
Error Message:
The data reader returned by the store data provider does not have enough columns for the query requested.
public ObjectResult<global::System.String> P_GET_MST_CODE(global::System.String i_RES_TYPE, ObjectParameter v_RESULT)
{
ObjectParameter i_RES_TYPEParameter;
if (i_RES_TYPE != null)
{
i_RES_TYPEParameter = new ObjectParameter("I_RES_TYPE", i_RES_TYPE);
}
else
{
i_RES_TYPEParameter = new ObjectParameter("I_RES_TYPE", typeof(global::System.String));
}
return base.ExecuteFunction<global::System.String>("P_GET_MST_CODE", i_RES_TYPEParameter, v_RESULT);
}
Below is the definition of the stored procedure.
<Function Name="P_GET_MST_CODE" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="LEGACY">
<Parameter Name="I_RES_TYPE" Type="varchar2" Mode="In" />
<Parameter Name="V_RESULT" Type="varchar2" Mode="Out" />
</Function>
Can anyone help me to solve this problem?
I've solved this by avoiding entity connection object. :-)
Until now, It seems to be unsupported for OUT Parameter of ORACLE Database.
Below is the changed code example.
using System.Data;
using System.Data.Common;
using System.Data.EntityClient;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Server;
using Oracle.DataAccess.Client;
.......
[Invoke]
public string method(string OTL)
{
DbCommand cmd = (((EntityConnection)this.ObjectContext.Connection).StoreConnection).CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "LoveMe";
OracleParameter ep = new OracleParameter("I_RES_TYPE", OTL);
ep.OracleDbType = OracleDbType.Varchar2;
ep.Direction = ParameterDirection.Input;
OracleParameter epV_RESULT = new OracleParameter("V_RESULT", null);
epV_RESULT.OracleDbType = OracleDbType.Varchar2;
epV_RESULT.Size = 30;
epV_RESULT.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ep);
cmd.Parameters.Add(epV_RESULT);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
string result = cmd.Parameters[1].Value.ToString(); //What I want to get.
cmd.Connection.Close();
return result;
}
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