I have a method that runs through a loop that can take quite a while to complete as it requires getting data back form an API.
What I would like to do is display a message on the front end explaining how the system is progressing during each loop. Is there a way to update the front end while processing?
public static void GetScreenshot(List<string> urlList, List<DesiredCapabilities> capabilities, String platform, Literal updateNote)
{
foreach (String url in urlList)
{
String siteName = new Uri(url).Host;
String dir = AppDomain.CurrentDomain.BaseDirectory+ "/Screenshots/" + siteName + "/" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm");
foreach (DesiredCapabilities cap in capabilities)
{
String saveDirectory = "";
if (platform == "btnGenDesktopScreens")
{
saveDirectory = dir + "/" + cap.GetCapability("os") + "-" + cap.GetCapability("os_version") + "-" + cap.GetCapability("browser") + cap.GetCapability("browser_version");
}
else if(platform == "btnMobile")
{
saveDirectory = dir + "/" + cap.GetCapability("platform") + "" + cap.GetCapability("device") + "-" + cap.GetCapability("browserName");
}
updateNote.Text += "<br/>" + cap.GetCapability("platform") + " - " + cap.GetCapability("device") + "-" + cap.GetCapability("browserName");
//I'd like to display a message here
TakeScreenshot(url, cap, saveDirectory);
//I'd like to display a message here
}
}
}
Has anyone come across a method of doing this?
Depending on how you're returning the feedback to the user, you might be able to do this by using HttpResponse.Flush in a loop to push parts of the HTML response to the user a bit at a time. See https://msdn.microsoft.com/en-us/library/system.web.httpresponse.flush(v=vs.100).aspx
Related
I made script task that's downloading and saving on disk two spreadsheets from Google Drive using file ID and prepared URL address.
This is main() from my C# code, there are no things outside of it:
public void Main()
{
string m_FileId = Dts.Variables["User::varFileId"].Value.ToString();
string m_RemoteUrl = "https://docs.google.com/spreadsheets/d/" + m_FileId + "/export?format=xlsx";
string m_FilePath = null;
WebClient client = new WebClient();
try
{
m_FilePath = Dts.Variables["User::varFilePath"].Value.ToString() + Dts.Variables["User::varFileName"].Value.ToString();
client.DownloadFile(new System.Uri(m_RemoteUrl), m_FilePath);
m_FilePath = "";
m_FileId = Dts.Variables["User::varFileId2"].Value.ToString();
m_RemoteUrl = "https://docs.google.com/spreadsheets/d/" + m_FileId + "/export?format=xlsx";
m_FilePath = Dts.Variables["User::varFilePath"].Value.ToString() + Dts.Variables["User::varFileName2"].Value.ToString();
client.DownloadFile(new System.Uri(m_RemoteUrl), m_FilePath);
}
catch(Exception e)
{
Dts.Events.FireError(0, "FileDownload", e.Message
+ "\r" + e.StackTrace
+ " \rUrl: " + m_RemoteUrl
+ " \rFilePath: " + m_FilePath
+ " \rPath: " + Dts.Variables["User::varFilePath"].Value.ToString()
+ " \rFileName2: " + Dts.Variables["User::varFileName2"].Value.ToString()
, string.Empty, 0);
Dts.TaskResult = (int)ScriptResults.Failure;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Problem occurs exactly on every second time I run this code and I don't know how to get rid of it. There's just exception in my script task. I'm printing all variables that are used in this code, and as you can see there's something wrong with m_FilePath, it's like multiplied despite of being printed just once.
[FileDownload] Error: An exception occurred during a WebClient request.
at System.Net.WebClient.DownloadFile(Uri address, String fileName)
at ST_84b63d1593dd449886eb2b32dff40b2d.ScriptMain.Main()
Url: https://docs.google.com/spreadsheets/d/----------/export?format=xlsx
FilePath: C:\Google Drive extract\ga_manual_cost_file.xlsxC:\Google Drive extract\ga_manual_cost_file.xlsx
Path: C:\Google Drive extract\ga_manual_cost_file.xlsx
FileName2: ga_manual_cost_file.xlsx
SSIS variables that I'm using are ReadOnly, and are used only in this script task(I tried running only this part of control flow), and their values are as follows:
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + txtFirstName.Text[0] + txtMiddle.Text + txtLastName.Text + "\r\n" +txtStreet.Text + "\r\n"+ cboCity.Text);
}
I'm trying to get 1 character white space inbetween cboTitle.Text, txtFirname.Text, txtMiddle.Text, and txtLastName, but they all output the information together, but I want them spaced evenly. what do I need to do? thanks in advance.
I'm going to post some other code thats below the one above in my project, just in case it might be relevant.
string AssembleText(string Title, string FirstName, string MiddleInitial, string LastName, string AddressLines, string City )
{
string Result = "";
Result += Title + " ";
Result += FirstName.Substring(0, 2) + " ";
// Only append middle initial if it is entered
if (MiddleInitial != "")
{
Result += MiddleInitial + " ";
}
Result += LastName + "\r\n";
// Only append items from the multiline address box
// if they are entered
if ( AddressLines != "")
{
Result += AddressLines + "\r\n";
}
//if (AddressLines.Length > 0 && AddressLines.ToString() != "")
//{
// Result += AddressLines + "\r\n";
//}
Result += City;
return Result;
}
}
}
If you just want a space between those specific fields in btnAssemble_Click, you can just insert them like this:
string myStr = foo + " " + bar + " " + baz;
So your first function would be modified to read:
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + " " + txtFirstName.Text[0] + " " + txtMiddle.Text + " " + txtLastName.Text + "\r\n" + txtStreet.Text + "\r\n" + cboCity.Text);
}
A few other comments:
It's not clear to me what the AssembleText() function you posted has to do with this. I am confused though, as I see a few lines appending spaces at the end just like I mentioned above.
Using the String.Format() function may make this code easier to read and maintain.
Using Environment.NewLine instead of "\r\n" will make the string contain the newline character defined for that specific environment.
Using a StringBuilder object may be faster over concatenation when building strings inside of a loop (which may not apply here).
Using String.format() should feet the bill. It also make your code easy to read.
txt.assembled.text = String.Format("{0} {1} {2} {3}",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text
);
It would be like this
private void btnAssemble_Click(object sender, EventArgs e)
{
txtAssembled.Text = (cboTitle.Text + " " + txtFirstName.Text[0] + " " +txtMiddle.Text + " " + txtLastName.Text + "\r\n" +txtStreet.Text + "\r\n"+ cboCity.Text);
}
It seems that you want String.Join; whenever you want to combine strings with a delimiter, say, " " (space) all you need is to put
String combined = String.Join(" ",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text);
Complete implementation (joining by space and new line) could be
txtAssembled.Text = String.Join(Environment.NewLine,
String.Join(" ",
cboTitle.Text,
txtFirstName.Text[0],
txtMiddle.Text,
txtLastName.Text),
txtStreet.Text,
cboCity.Text);
I'm provided with 2 Excel files that I convert to TSV files and in the end have to deliver in a TSV file. The 1st file is the main file (strWorksheetPath) and all lines have to be included. The 2nd file (PrintPath) has additional information but not each line in the main file has extra information. To do this in C# I followed this msdn guide to do what I have to do and it's working fine. Unfortunatly, file 1 has 23 columns and file 2 has 10 adding up to 33 columns and so 33 properties in total. I created some temp classes to see if everything is working but it looks very messy in my opinion.
Is there a way to clean up my code and make it look more tidy by possibly not having to make temp classes, condense some repetitive code, ...?
public static void ConvertTSVtoMontDataTable(string strWorksheetPath, string strPrintPath,
bool closeConnection = true)
{
// Check if the main file exist.
if (!File.Exists(strWorksheetPath)) return;
// Load both files.
var mainFile = File.ReadAllLines(strWorksheetPath);
var extraFile = File.ReadAllLines(strPrintPath);
// Create 2 lists.
var mainLines = mainFile.Select(line => new TempMainLine(line)).ToList();
var extraLines = extraFile.Select(line => new TempExtraLine(line)).ToList();
var lines = new List<TempLine>();
// Merge both files.
var leftOuterJoinQuery =
from worksheetLine in mainLines
join printLine in extraLines on string.Concat(worksheetLine.prop6, worksheetLine.prop8) equals
string.Concat(printLine.prop4, printLine.prop5) into lineGroup
from line in lineGroup.DefaultIfEmpty()
select
new TempLine(worksheetLine.prop0, worksheetLine.prop1, worksheetLine.prop2, worksheetLine.prop3,
worksheetLine.prop4, worksheetLine.prop5, worksheetLine.prop6, worksheetLine.prop7,
worksheetLine.prop8, worksheetLine.prop9, worksheetLine.prop10, worksheetLine.prop11,
worksheetLine.prop12, worksheetLine.prop13, worksheetLine.prop14, worksheetLine.prop15,
worksheetLine.prop16, worksheetLine.prop17, worksheetLine.prop18, worksheetLine.prop19,
worksheetLine.prop20, worksheetLine.prop21, worksheetLine.prop22, line == null ? "" : line.prop0,
line == null ? "" : line.prop1, line == null ? "" : line.prop2, line == null ? "" : line.prop3,
line == null ? "" : line.prop4, line == null ? "" : line.prop5, line == null ? "" : line.prop6,
line == null ? "" : line.prop7, line == null ? "" : line.prop8, line == null ? "" : line.prop9);
foreach (var tempLine in leftOuterJoinQuery)
{
lines.Add(tempLine);
}
// Write output to new temp file (TESTING)
using (
var file =
new StreamWriter(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"output.txt")))
{
foreach (var item in lines)
{
file.WriteLine(item.prop0 + (char)9 + item.prop1 + (char)9 + item.prop2 + (char)9 + item.prop3 +
(char)9 + item.prop4 + (char)9 + item.prop5 + (char)9 + item.prop6 + (char)9 +
item.prop7 + (char)9 + item.prop8 + (char)9 + item.prop9 + (char)9 + item.prop10 +
(char)9 + item.prop11 + (char)9 + item.prop12 + (char)9 + item.prop13 + (char)9 +
item.prop14 + (char)9 + item.prop15 + (char)9 + item.prop16 + (char)9 +
item.prop17 + (char)9 + item.prop18 + (char)9 + item.prop19 + (char)9 +
item.prop20 + (char)9 + item.prop21 + (char)9 + item.prop22 + (char)9 +
item.prop23 + (char)9 + item.prop24 + (char)9 + item.prop25 + (char)9 +
item.prop26 + (char)9 + item.prop27 + (char)9 + item.prop28 + (char)9 +
item.prop29 + (char)9 + item.prop30 + (char)9 + item.prop31 + (char)9 +
item.prop32);
}
}
}
I thought about this some more and regardless of what your Temp* classes look like, something along the lines of the below will work given the assumption that (based on the code you presented), you're outputting every column from both files in the order in which they came in. If you needed to exclude fields, change the order, etc., that would require some changes to the below or a different solution entirely.
It's basically just reading those two files in, joining on the Split() result and then combining the two lines. I didn't see a point in handling the LOJ logic for a null printFile line but if you need the extra tabs, you could replace the line ?? "" with something like line ?? new String('\t', 10)
Note that this is probably not the most efficient way to go about this and if your files are huge, you'd definitely want to optimize this a bit.
// Merge both files.
var lines =
from worksheetLine in mainFile
join printLine in extraFile on string.Concat(worksheetLine.Split('\t')[6], worksheetLine.Split('\t')[8]) equals
string.Concat(printLine.Split('\t')[4], printLine.Split('\t')[5]) into lineGroup
from line in lineGroup.DefaultIfEmpty()
select string.Concat(worksheetLine, line ?? "");
// Write output to new temp file (TESTING)
using (
var file =
new StreamWriter(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"output.txt")))
{
foreach (var item in lines)
{
file.WriteLine(item);
}
}
How to show annotation present in an entity in popup window by using html web resource. My requirement is to display annotation present in an entity in a popup window and in popup window user should be able to delete , upload and convert the annotation to pdf (if he wants). Can you suggest a best method to achieve this in crm 2011.
function retann() {
//debugger;
var serverUrl = Xrm.Page.context.getServerUrl();
var GUIDvalue = Xrm.Page.data.entity.getId();
// Creating the Odata Endpoint
var oDataPath = "http://url/organization/XRMServices/2011/OrganizationData.svc/";
var retrieveReq = new XMLHttpRequest();
var Odata = oDataPath + "/AnnotationSet?$select=DocumentBody,FileName,MimeType,ObjectId&$filter=ObjectId/Id eq guid'" + GUIDvalue + "'";
retrieveReq.open("GET", Odata, false);
retrieveReq.setRequestHeader("Accept", "application/json");
retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveReq.onreadystatechange = function () { retrieveReqCallBack(this); };
retrieveReq.send();
}
function retrieveReqCallBack(retrieveReq) {
if (retrieveReq.readyState == 4 /* complete */) {
//debugger;
var retrieved = this.parent.JSON.parse(retrieveReq.responseText).d;
var message = "";
var fun_var =
"<script type=text/javascript>" +
"function result_value()" +
"{" +
"var rad_val;" +
"for (var i=0; i < document.orderform.test.length; ++i){if (document.orderform.test[i].checked){rad_val = document.orderform.test[i].value;}}" +
"if(rad_val==null || rad_val=='')" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue('0');" +
"}" +
"else" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue(rad_val);" +
"}" +
" window.top.opener.Xrm.Page.data.entity.attributes.get('new_fireplugin').setValue(1);" +
"window.top.opener.Xrm.Page.data.entity.save();" +
"this.window.close();" +
"}" +
"function result_value1()" +
"{" +
"var rad_val1;" +
"for (var i=0; i < document.orderform.test.length; ++i){if (document.orderform.test[i].checked){rad_val1 = document.orderform.test[i].value;}}" +
"if(rad_val1==null || rad_val1=='')" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue('0');" +
"}" +
"else" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue(rad_val1);" +
"}" +
" window.top.opener.Xrm.Page.data.entity.attributes.get('new_delete').setValue(1);" +
"window.top.opener.Xrm.Page.data.entity.save();" +
"this.window.close();" +
"}" +
"</script>";
var n = retrieved.results.length;
for (var i = 0; i < retrieved.results.length; i++) {
message += " <input type='radio' name='test' value=' " + i + "' />" + retrieved.results[i].FileName + "<br />";
}
myWindow = window.open('', '', 'width=500,height=150,left=250,top=250,scrollbars=yes,resizable=yes,directories=yes');
myWindow.document.write(fun_var + "<body bgcolor=GhostWhite style='font-family:verdana;font-size:11px;'><form name='orderform' style='font-family:verdana;font-size:11px;'>" + message + "</br><center ><input type='button' onclick='result_value()' style='font-family:verdana;font-size:11px;' value='Convert To PDF'/></center>" + "</form>");
myWindow.focus();
}
}
function SetField() {
var AddressType = Xrm.Page.data.entity.attributes.get("new_radiovalue");
AddressType.setValue("");
}
function save_form() {
// var MainPhone = Xrm.Page.data.entity.attributes.get("new_name").getValue();
//Xrm.Page.data.entity.attributes.get("new_name").setValue(MainPhone+".");
Xrm.Page.data.entity.save();
}
retrieveReqCallBack(this) function displays the popup with annoatation. Using the above code i'm able to convert doc to pdf. Since i want to add multiple functionalities like upload , delete and convert to pdf. If annotation is present then popup should have option to upload and if annotation is present then it has to show delete and convert to pdf buttons.
I found this as solution to my question,
You'll need to create a custom web resource (html) with javascript to pull the data out of the sub-grid, parse the rows, query the crm data via REST or SOAP to see if there is an annotation, then put an icon of the 'paperclip' which'll allow users to upload attachments against that record.
I'm currently working on an ASP.NET project where I'm using the Google Maps API to show a marker for every company that's registrated in the database.
Everything works just fine, but when I click on a marker the tooltip/dialogbox for the last company in my company list always shows up and not the actualy company mark that's been clicked on.
I can't really get my head around why it is always the last marker that shows up. Here's my updated code:
JavaScript.Text = #"<script type='text/javascript'>
function load() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(56.4, 10.57983), 9);
map.enableScrollWheelZoom();
}
}
</script> ";
foreach (MemberProfile m in relatedMembers)
{
XmlDocument doc = new XmlDocument();
string address = m.Address;
string zip = m.Zip;
string city = m.City;
string navn = m.Name;
string tlf = m.Phone;
doc.Load("http://maps.googleapis.com/maps/api/geocode/xml?address=" + zip + "+" + city + "+" + address + "+DK&sensor=true&key=ABQIAAAAEaY4JLb9fZFGMlDKuMUlWBRSvyGIkBO7X03pzlT7Z30EPXHR8BS0rXL_ShFm2gc79lZTw2Zak88wng");
XmlNode latNode = doc.SelectSingleNode("GeocodeResponse/result/geometry/location/lat/text()");
XmlNode lonNode = doc.SelectSingleNode("GeocodeResponse/result/geometry/location/lng/text()");
if (latNode != null && lonNode != null)
{
JSAddMarkers.Text += #"<script type='text/javascript'>
var marker = new GMarker(new GLatLng(" + latNode.Value + "," + lonNode.Value + ")); "
+ "var html = '<b>" + navn + "</b><br />" + address + "<br /> " + zip + " " + city + "<br />" + tlf + "'; " + "GEvent.addListener(marker, 'click', function() { marker.openInfoWindowHtml(html); });"
+ "map.addOverlay(marker);"
+ "</script>";
}
If any of you out there can spot the reason why, I would be happy to hear from you! Any help/hint is appreciated :-)
All the best,
Bo
try this
var point =new GLatLng(" + latNode.Value + "," + lonNode.Value + ");
var marker = createMarker(point, address,zip,city,navn);
map.addOverlay(marker);
function createMarker(point, address, zip,city, navn) {
var marker = new GMarker(point, customIcons[type]);
var html = "Address:<b style='padding-left:6px'>" + address+ "</b><br/>zip:<b style='padding-left:6px'>"+ zip+ "</b><br/>city:<b style='padding-left:6px'>"+ city+ "</b>";
GEvent.addListener(marker, 'mouseover', function() {
marker.openInfoWindowHtml(html);
});
GEvent.addListener(marker, "mouseout", function() {
marker.closeInfoWindow();
});
return marker;
}