We use PuppeteerSharp to add the ability for users to download a PDF of our application. Unfortunately sometimes a huge number of Chromium processes are started and don't stop until a server restart.
Normally when a user downloads a pdf, 5 chromium processes start and those disappear when the download is finished.
This is our code:
private static LaunchOptions launchOptions = new LaunchOptions
{
ExecutablePath = chromepath,
Headless = true,
DefaultViewport = ViewPortOptions
};
public static void ExportPdf(string url, string location)
{
try
{
Task<string> task = Task.Run<string>(async () => await ExportPdfASync(url, location)));
task.Wait();
}
catch (Exception)
{
// Exception handling
}
}
public static async Task<string> ExportPdfASync(string url, string location)
{
using (var browser = await Puppeteer.LaunchAsync(LaunchOptions))
using (var page = await browser.NewPageAsync())
{
await page.SetViewportAsync(new ViewPortOptions() { Width = 1440, Height = 990, IsMobile = false, DeviceScaleFactor = 1.0 });
await page.SetJavaScriptEnabledAsync(true);
await page.GoToAsync(url);
await page.WaitForTimeoutAsync(1500);
var marginOptions = new MarginOptions()
{
Top = "10mm",
Left = "10mm",
Right = "10mm",
Bottom = "10mm"
};
var pdfOptions = new PdfOptions()
{
PrintBackground = true,
Format = PaperFormat.A4,
MarginOptions = marginOptions,
Landscape = landscape
};
await page.PdfAsync(location, pdfOptions);
}
return "";
}
The browser and page are in the using blocks so, even with an error those should be disposed.
Does anyone have a solution for this problem? We, and our servers would be very happy;)
Try this:
public static async Task<string> ExportPdfASync(string url, string location)
{
try
{
using (var browser = await Puppeteer.LaunchAsync(LaunchOptions))
using (var page = await browser.NewPageAsync())
{
await page.SetViewportAsync(new ViewPortOptions() { Width = 1440, Height = 990, IsMobile = false, DeviceScaleFactor = 1.0 });
await page.SetJavaScriptEnabledAsync(true);
await page.GoToAsync(url);
await page.WaitForTimeoutAsync(1500);
var marginOptions = new MarginOptions()
{
Top = "10mm",
Left = "10mm",
Right = "10mm",
Bottom = "10mm"
};
var pdfOptions = new PdfOptions()
{
PrintBackground = true,
Format = PaperFormat.A4,
MarginOptions = marginOptions,
Landscape = landscape
};
await page.PdfAsync(location, pdfOptions);
}
}
catch (Exception ex)
{
}
finally {
browser.CloseAsync();
page.CloseAsync();
}
return "";
}
Related
I have problem getting output from html2canvas JS library within Chrome automated by selenium.
Response is always null, but I can see in the Chrome console that code executed successfully and screenshot has been encoded
public byte[] TakeScreenshot(string fileName)
{
this.logger.Debug($"Taking screenshot");
var seleniumDownloadPath = this.seleniumEngine.GetDownloadPath();
IJavaScriptExecutor js = Driver as IJavaScriptExecutor;
var html2canvasJs = System.IO.File.ReadAllText(Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), this.seleniumEngine.GetHtml2CanvasPath()));
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(60));
var response = new object { };
js.ExecuteScript(html2canvasJs);
string generateScreenshotJS =
var canvasImgContentDecoded;
#"function genScreenshot () {
html2canvas(document.body).then(function(canvas) {
window.canvasImgContentDecoded = canvas.toDataURL(""image/png"");
console.log(window.canvasImgContentDecoded);
return window.canvasImgContentDecoded;
});
}
genScreenshot();";
response = js.ExecuteScript(generateScreenshotJS);
}
I also tried solution from this Here but the behavior was unstable (e.g. when running realtime i got error of nulls, but if running using breakpoints, I got result sometime)
Finally found the solution after finding out that execution of script takes more time and variable was null. So added wait function to retrieve once its filled - window.canvasImgContentDecoded
public byte[] TakeScreenshot(string fileName)
{
this.logger.Debug($"Taking screenshot");
var seleniumDownloadPath = this.seleniumEngine.GetDownloadPath();
IJavaScriptExecutor js = Driver as IJavaScriptExecutor;
var html2canvasJs = System.IO.File.ReadAllText(Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), this.seleniumEngine.GetHtml2CanvasPath()));
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(60));
var response = new object { };
js.ExecuteScript(html2canvasJs);
string generateScreenshotJS =
#"
var canvasImgContentDecoded;
function genScreenshot () {
html2canvas(document.body).then(function(canvas) {
window.canvasImgContentDecoded = canvas.toDataURL(""image/png"");
console.log(window.canvasImgContentDecoded);
});
}
genScreenshot();";
response = js.ExecuteScript(generateScreenshotJS);
string getSCreenShot = "return window.canvasImgContentDecoded;";
var encodedPngContent = new object { };
/*ADDED WAIT FUNCTION*/
wait.Until(
wd =>
{
encodedPngContent = js.ExecuteScript(getSCreenShot);
if (encodedPngContent != null)
{
return true;
}
return false;
});
string pngContent = encodedPngContent.ToString();
pngContent = pngContent.Replace("data:image/png;base64,", string.Empty);
string fileSavePath = this.seleniumEngine.GetDownloadPath() + fileName;
File.WriteAllBytes(fileSavePath, Convert.FromBase64String(pngContent));
byte[] fileByte = System.IO.File.ReadAllBytes(fileSavePath);
File.Delete(fileSavePath);
return fileByte;
}
I'm trying to play video with AvPlayer in Xamarin.iOS. I'm working with Firebase Storage. If I upload video from android, media type is set as mp4 but from iOS, media type is set as urlencoded. I can play mp4 files with AvPlayer but urlencoded files are not playable. On the other hand, urlencoded files are playable in android VideoView. Do you have any idea about it?
Here my codes, first pick video from gallery:
private async void PickVideoButton_TouchUpInside(object sender, EventArgs e)
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickVideoSupported)
{
return;
}
try
{
file = await CrossMedia.Current.PickVideoAsync();
if (file == null)
{
return;
}
fileStream = await ConvertMovToMp4();
mediaType = "Video";
avp = new AVPlayer(NSUrl.FromFilename(file.Path));
avpvc = new AVPlayerViewController();
avpvc.Player = avp;
AddChildViewController(avpvc);
GeneralPostingStoryViewBackground.AddSubview(avpvc.View);
avpvc.View.Frame = GeneralPostingStoryImageView.Frame;
avpvc.ShowsPlaybackControls = true;
avp.Play();
}
catch (Exception ex)
{
alert = UIAlertController.Create("Error", "Gallery doesn't support", UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
PresentViewController(alert, true, null);
}
}
public async Task<Stream> ConvertMovToMp4()
{
string exportPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string exportFilePath = Path.Combine(exportPath, DateTime.Now.ToString() + ".mp4");
var asset = AVAsset.FromUrl(NSUrl.FromFilename(file.Path));
var length = asset.Duration.Seconds;
lengthDuration = Convert.ToInt32(length).ToString();
AVAssetExportSession export = new AVAssetExportSession(asset, AVAssetExportSession.PresetMediumQuality);
export.OutputUrl = NSUrl.FromFilename(exportFilePath);
export.OutputFileType = AVFileType.Mpeg4;
export.ShouldOptimizeForNetworkUse = true;
await export.ExportTaskAsync();
var stream = File.OpenRead(exportFilePath);
return stream;
}
Then, upload video to firebase storage:
private async void ShareButton_TouchUpInside(object sender, EventArgs e)
{
try
{
var result = await PortableSharediOS(ID, mediaType, fileStream, commentText);
if (result == "Success.")
{
CommonValues.viewControllerIndexList.RemoveAt(CommonValues.viewControllerIndexList.Count - 1);
NavigateViewController();
}
else
{
alert = UIAlertController.Create("Error", result.ToString(), UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
PresentViewController(alert, true, null);
}
}
catch (Exception ex)
{
alert = UIAlertController.Create("Error", "Check your internet connection.", UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
PresentViewController(alert, true, null);
}
}
Finally, I'm trying to play videos, as I said the mp4 files are playable which I've upload from android, but files which I've upload from iOS, avplayer doesn't play them..:
public async Task GetStory(int storyIndex)
{
var mediaType = stories[storyIndex].StoryType;
var story = stories[storyIndex];
user = await firebaseHelper.GetUser(story.StoryOwner);
if (mediaType == "Photo")
{
GetImage(story.MediaLink, storyViewStoryImageView);
GetImage(user.PhotoLink, storyViewImageView);
storyViewUserName.Text = user.UserName;
storyViewContentView.Text = story.Content;
time = story.MediaDuration;
storyViewDuration.Text = time.ToString();
}
else
{
storyViewUserName.Text = user.UserName;
storyViewContentView.Text = story.Content;
time = story.MediaDuration;
var asset = AVAsset.FromUrl(NSUrl.FromString(story.MediaLink));
var item = AVPlayerItem.FromAsset(asset);
avp = new AVPlayer(item);
avp.Muted = false;
avpvc = new AVPlayerViewController();
avpvc.Player = avp;
AddChildViewController(avpvc);
storyViewStoryImageView.AddSubview(avpvc.View);
avpvc.View.Hidden = false;
avpvc.View.Frame = storyViewStoryImageView.Frame;
avpvc.ShowsPlaybackControls = false;
avp.Play();
storyViewDuration.Text = time.ToString();
}
timer.Enabled = false;
timer.Close();
TimerTextVoid();
}
I can play all files on Android. Doesn't matter where they were uploaded from.
I figured out my problem. Download and save file to device from Firebase Storage. Then assign it to AVAsset. Codes:
public async Task GetStory(int storyIndex)
{
var mediaType = stories[storyIndex].StoryType;
var story = stories[storyIndex];
user = await firebaseHelper.GetUser(story.StoryOwner);
if (mediaType == "Photo")
{
GetImage(story.MediaLink, storyViewStoryImageView);
GetImage(user.PhotoLink, storyViewImageView);
storyViewUserName.Text = user.UserName;
storyViewContentView.Text = story.Content;
time = story.MediaDuration;
storyViewDuration.Text = time.ToString();
}
else
{
storyViewUserName.Text = user.UserName;
storyViewContentView.Text = story.Content;
time = story.MediaDuration;
var asset = await GetVideo(story.MediaLink);
var item = new AVPlayerItem(asset);
avp = new AVPlayer(item);
avp.Muted = false;
avpvc = new AVPlayerViewController();
avpvc.Player = avp;
AddChildViewController(avpvc);
storyViewStoryImageView.AddSubview(avpvc.View);
avpvc.View.Hidden = false;
avpvc.View.Frame = storyViewStoryImageView.Frame;
avpvc.ShowsPlaybackControls = false;
avp.Play();
storyViewDuration.Text = time.ToString();
}
timer.Enabled = false;
timer.Close();
TimerTextVoid();
}
public async Task<AVAsset> GetVideo(string url)
{
string videoFile;
using (var client = new WebClient())
{
var content = client.DownloadData(url);
var stream = new MemoryStream(content);
string folder = Path.GetTempPath();
videoFile = Path.Combine(folder, DateTime.Now.ToString() + ".mp4");
if (!System.IO.File.Exists(videoFile))
{
using (FileStream outputStream = System.IO.File.Create(videoFile))
{
await stream.CopyToAsync(outputStream);
}
}
}
var asset = AVUrlAsset.FromUrl(NSUrl.FromFilename(videoFile));
return asset;
}
We have a web API application which runs on .net4.6.1. We have tried several times to figure out the root cause where it is getting deadlock, but failed. Below is the code snippet. We are hitting this API endpoint every 1 minute. It will pick 300 transaction at a time for processing from the DB. We have observed that it get stuck when there are no files to process from the DB. Not sure though. It would be helpful if someone can help us.TIA
public class TaxEngineIntegratorController : ApiController
{
public async Task Get(int id)
{
try
{
await MainFileMethod();
}
catch (Exception Ex)
{
SerilogMethods.LogError(log, Ex, "Get");
}
}
public async Task MainFileMethod()
{
List<FileTransaction> lstFTtoLock = new List<FileTransaction>();
try
{
List<int> lstStatusIds = new List<int>();
lstStatusIds.Add(objStatusManager.GetStatusIdbyName(Status.ConversionToXmlSucceded));
lstStatusIds.Add(objStatusManager.GetStatusIdbyName(Status.Reprocess));
//Getting the serviceURL of TRTaxEngine
string seriviceURL = objConfigManager.GetConfigurationdbyKey(ConfigurationList.TRTaxEngineURL);
//Getting the output path for the file to be placed after processing
string outputfilePath = objConfigManager.GetConfigurationdbyKey(ConfigurationList.TRTaxOutputXMLFolder);
FileMasterManager objFileMasterManager = new FileMasterManager();
TRTaxXMLOperations objxmlresp = new TRTaxXMLOperations();
//Getting all the files list for proccessing from the DB
List<FileTransaction> lstFiletoProcess = await objTransManager.GetFileListforProcessingAsync(lstStatusIds, true);
lstFTtoLock = lstFiletoProcess;
if (lstFiletoProcess.Count == 0)
return;
if (lstFiletoProcess.Count > 0)
{
var tasks = new List<Task<string>>();
using (HttpClient httpClnt = new HttpClient())
{
httpClnt.Timeout = TimeSpan.FromMilliseconds(-1);
foreach (FileTransaction item in lstFiletoProcess)
{
TRXMLResponseModel objRespModel = new TRXMLResponseModel();
objRespModel.strxmlResponse = string.Empty;
string fullFileName = item.FilePath + item.ConvertedName;
objRespModel.outputFilename = outputfilePath + item.ConvertedName;
FileMaster fileMaster = objFileMasterManager.GetById(item.FileId);
//Proccessing the file and getting the output filedata
Task<string> t = objxmlresp.GetXMLResponse(seriviceURL, fullFileName, fileMaster.CountryId.GetValueOrDefault(), httpClnt, objFileOperation, objRespModel.outputFilename, item);
tasks.Add(t);
objRespModel.strxmlResponse = await t;
}
var result = await Task.WhenAll(tasks);
}
SerilogMethods.LogCustomException(log, "Http Client Destroyed in Tax Engine", "GetXMLResponse");
}
}
catch (Exception Ex)
{
if (lstFTtoLock != null && lstFTtoLock.Count > 0)
{
objTransManager.UpdateFileTransactionIsPickedtoFalse(lstFTtoLock);
}
throw Ex;
}
}
}
//Getting all the files list for proccessing from the DB
public async Task<List<FileTransaction>> GetFileListforProcessingAsync(List<int> lstStatusList, bool IsActive)
{
try
{
List<FileTransaction> lstFTList = new List<FileTransaction>();
using (SUTBACDEVContext db = new SUTBACDEVContext())
{
//DataTable dtFileTransactions = GetFileTransactionListAsync(lstStatusList, IsActive);
string connectionString = db.Database.GetDbConnection().ConnectionString;
var conn = new SqlConnection(connectionString);
string query = #"[SUTGITA].[GetFileListforProcessing]";
using (var sqlAdpt = new SqlDataAdapter(query, conn))
{
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlAdpt.SelectCommand.Parameters.AddWithValue("#StatusId", string.Join(",", lstStatusList.Select(n => n.ToString()).ToArray()));
sqlAdpt.SelectCommand.Parameters.AddWithValue("#IsActive", IsActive);
sqlAdpt.SelectCommand.CommandTimeout = 60000;
DataTable dtFileTransactions = new DataTable();
sqlAdpt.Fill(dtFileTransactions);
if (dtFileTransactions != null && dtFileTransactions.Rows.Count > 0)
{
IEnumerable<long> ids = dtFileTransactions.AsEnumerable().ToList().Select(p => p["id"]).ToList().OfType<long>();
lstFTList = await db.FileTransaction.Include(x => x.File.Country).Where(x => ids.Contains(x.Id)).OrderBy(x => x.Id).ToListAsync();
}
}
}
return lstFTList;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<string> GetXMLResponse(string baseUrl, string fullFileName, int countryId, HttpClient client, FileOperations objFileOperation, string outputfilePath, FileTransaction item)
{
try
{
var fileData = new StringBuilder(objFileOperation.ReadFile(fullFileName));
using (HttpContent content = new StringContent(TransformToSOAPXml(fileData, countryId), Encoding.UTF8, "text/xml"))
{
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, baseUrl))
{
request.Headers.Add("SOAPAction", "");
request.Content = content;
using (HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
{
using (Stream streamToWriteTo = File.Open(outputfilePath, FileMode.Create))
{
await streamToReadFrom.CopyToAsync(streamToWriteTo);
}
}
var transactionEntry = new FileTransaction
{
FileId = item.FileId,
FilePath = outputfilePath,
ConvertedName = item.ConvertedName,
ActionedBy = Process.Process3,
TimeStamp = DateTime.UtcNow,
StatusId = objStatusManager.GetStatusIdbyName(Status.OutputXmlReceived),
IsActive = true,
CreatedBy = Others.Scheduler,
CreatedOn = DateTime.UtcNow,
ModifiedBy = Others.Scheduler,
ModifiedOn = DateTime.UtcNow
};
//Inserting the new record and Updating isActive filed of previous record in Tranasaction table(Calling updateDataonTRSuccess method of TRTaxXMLOperations class)
await updateDataonTRSuccessAsync(item, transactionEntry);
return "Success";
}
else
{
SerilogMethods.LogCustomException(log, "Error occured in Tax Engine", "GetXMLResponse");
//Log the SOAP response when the SOAP fails with an error message
if (response.Content != null)
{
throw new Exception(await response.Content.ReadAsStringAsync());
}
return null;
}
}
}
}
}
catch (Exception ex)
{
SerilogMethods.LogError(log, ex, "GetXMLResponse");
return null;
}
}
The following changes I have done to make it work to this specific method.
Removal of this line : objRespModel.strxmlResponse = await t;
and added configureawait(false) to this line :List lstFiletoProcess = await objTransManager.GetFileListforProcessingAsync(lstStatusIds, true).ConfigureAwait(false); Below is the working code
public async Task MainFileMethod()
{
List<FileTransaction> lstFTtoLock = new List<FileTransaction>();
try
{
List<int> lstStatusIds = new List<int>();
lstStatusIds.Add(objStatusManager.GetStatusIdbyName(Status.ConversionToXmlSucceded));
lstStatusIds.Add(objStatusManager.GetStatusIdbyName(Status.Reprocess));
//Getting the serviceURL of TRTaxEngine
string seriviceURL = objConfigManager.GetConfigurationdbyKey(ConfigurationList.TRTaxEngineURL);
//Getting the output path for the file to be placed after processing
string outputfilePath = objConfigManager.GetConfigurationdbyKey(ConfigurationList.TRTaxOutputXMLFolder);
FileMasterManager objFileMasterManager = new FileMasterManager();
TRTaxXMLOperations objxmlresp = new TRTaxXMLOperations();
//Getting all the files list for proccessing from the DB
List<FileTransaction> lstFiletoProcess = await objTransManager.GetFileListforProcessingAsync(lstStatusIds, true).ConfigureAwait(false);
lstFTtoLock = lstFiletoProcess;
if (lstFiletoProcess.Count == 0)
return;
if (lstFiletoProcess.Count > 0)
{
var tasks = new List<Task<string>>();
using (HttpClient httpClnt = new HttpClient())
{
httpClnt.Timeout = TimeSpan.FromMilliseconds(-1);
//Getting the files for processing
foreach (FileTransaction item in lstFiletoProcess)
{
TRXMLResponseModel objRespModel = new TRXMLResponseModel();
objRespModel.strxmlResponse = string.Empty;
string fullFileName = item.FilePath + item.ConvertedName;
objRespModel.outputFilename = outputfilePath + item.ConvertedName;
FileMaster fileMaster = objFileMasterManager.GetById(item.FileId);
//Proccessing the file and getting the output filedata
Task<string> t = objxmlresp.GetXMLResponse(seriviceURL, fullFileName, fileMaster.CountryId.GetValueOrDefault(), httpClnt, objFileOperation, objRespModel.outputFilename, item, objTransManager);
tasks.Add(t);
//objRespModel.strxmlResponse = await t;
}
var result = await Task.WhenAll(tasks);
}
}
}
catch (Exception Ex)
{
if (lstFTtoLock != null && lstFTtoLock.Count > 0)
{
objTransManager.UpdateFileTransactionIsPickedtoFalse(lstFTtoLock);
}
throw Ex;
}
}
My Recommendation:
The method "Get(int id)" is somewhat confusing. first, it takes "id" and does nothing with it. Also it return nothing so it is not a "Get" method. It is basically asking for all transactions with status "Status.ConversionToXmlSucceded" & "Status.Reprocess" and are active to be gotten and processed via the "objxmlresp.GetXMLResponse" method... You Dont Have To Await the "MainFileMethod();" in "Get(int id)" just return the task or return Ok(); and allow all the process to go on in the background. You can experiment with reducing the "sqlAdpt.SelectCommand.CommandTimeout = 60000;".
I'm getting an exception: Navigation failed because browser has disconnected.
After my code gets executed, it will close by the using block.
What is the main reason for the browser to disconnect?.
Here's the exception that I get:
Error on finding navigate urls, screenshot and outgoing urls for Google id 78659 for location in in iteration 0 and error message is :
PuppeteerSharp.NavigationException: Navigation failed because browser
has disconnected! (NetworkManager failed to process
Fetch.requestPaused. Frame 6CCD5A551750D9DF102ABCF53D90B6EB not found.
at
PuppeteerSharp.Helpers.AsyncDictionaryHelper`2.<>c__DisplayClass4_0.b__0()
This is my code:
using (var destinationUrlBrowser = await Puppeteer.LaunchAsync(launchOptions))
{
using (var page = await destinationUrlBrowser.NewPageAsync())
{
try
{
var viewPortOptions = new ViewPortOptions{Width = 1366, Height = 768};
await page.SetViewportAsync(viewPortOptions);
await page.AuthenticateAsync(new Credentials{Username = _luminatiUserName, Password = _luminatiPassword});
var timeout = new NavigationOptions{Timeout = 50000};
Response response;
try
{
response = await page.GoToAsync(destinationUrl, 1 * 50000);
}
catch (Exception)
{
response = await page.ReloadAsync(timeout);
}
await Task.Delay(2000);
var pageSource = await page.GetContentAsync();
if (string.IsNullOrEmpty(pageSource) || pageSource.Contains("Proxy Error"))
{
isDestinationPageSourceNotFound = true;
}
if (!isDestinationPageSourceNotFound)
{
var screenShotOptions = new ScreenshotOptions{FullPage = true, Type = ScreenshotType.Jpeg, Quality = 50};
Log.Info($"Taking screen shot for {network} id {Id} for location {country}!");
await page.ScreenshotAsync(screenShotUrl, screenShotOptions);
var chain = response.Request.RedirectChain;
var redirects = new HashSet<string>();
for (var index = 0; index < chain.Length - 1; index++)
{
redirects.Add(chain[index].Url);
}
destinationInfo.Redirects = redirects.ToList();
var currentUrl = response.Request.Url;
for (int i = 0; i < 2; i++)
{
response = await page.GoToAsync(currentUrl);
var currentUrl1 = response.Request.Url;
if (currentUrl != currentUrl1)
{
currentUrl = currentUrl1;
continue;
}
else
{
currentUrl = currentUrl1;
break;
}
}
destinationInfo.DestinationUrl = currentUrl;
Log.Info($"Found {destinationInfo.Redirects.Count} redirect urls from {network} id {Id} for location {country}!");
destinationInfo.HtmlPageSource = pageSource;
using (var outputFile = new StreamWriter(indexHtml))
{
await outputFile.WriteAsync(pageSource);
}
destinationInfo.HtmlContent = Helper.RemoveStyleAndScript(destinationInfo.HtmlPageSource);
using (var outputFile = new StreamWriter(htmlContentUrl))
{
await outputFile.WriteAsync(destinationInfo.HtmlContent);
}
ZipFile.CreateFromDirectory(basePath, zipPath);
destinationInfo.LocalHtmlPath = zipPath;
destinationInfo.LocalScreenShot = screenShotUrl;
outgoingUrls = Helper.GetOutgoingUrl(pageSource, currentUrl);
Log.Info($"Found {outgoingUrls.Count} outgoing urls from {network} id {Id} for location {country}!");
foundDetails = true;
}
}
catch (Exception e)
{
Log.Info($"Error on finding navigate urls, screenshot and outgoing urls for {network} id {Id} for location {country} in iteration {iterate} and error message is : {e}");
if (iterate > 1)
{
isDestinationPageSourceNotFound = true;
}
}
}
}
If your code used to work, and it stopped working all of a sudden.
You won't believe it! Chrome version matters so basically if you are using
Version 83.0.4103.61 (Official Build) (64-bit), it will fail and show "Navigation failed because browser has disconnected!" Error.
downgrade your chrome to Version 81.0.4044.138 (Official Build) (64-bit) or below 7X.XX.XXXX.XXX
Note: Make sure you do the same in your server as well. Not just locally
I'm using the geolocator plugin to retrieve my current location and add a pin to the page. Here is the service for this:
tasks.cs
public async Task<Plugin.Geolocator.Abstractions.Position> GetDeviceCurrentLocation()
{
try
{
var locator = Plugin.Geolocator.CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await locator.GetPositionAsync(TimeSpan.FromSeconds(1));
if (position != null)
{
return position;
}
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
return new Plugin.Geolocator.Abstractions.Position();
}
I'm trying to use it in the view like this :
public MapPage(List<Models.xxx> xxx, Models.yyy yyy )
{
InitializeComponent();
Tasks ts = new Tasks();
var myLocation = ts.GetDeviceCurrentLocation();
var latitudeIm = myLocation.Result.Latitude;
var longitudeIm = myLocation.Result.Longitude;
var pin1 = new Pin
{
Type = PinType.Place,
Position = new Position(latitudeIm, longitudeIm),
Title = "My Location"
};
customMap.Pins.Add(pin1);
}
My application breaks when I try this code var latitudeIm = myLocation.Result.Latitude;
I guess since I have a async task the result must be awaited. Any idea how can I use the public async Task<Plugin.Geolocator.Abstractions.Position> GetDeviceCurrentLocation() data in my view?
You should use await for async method;
var myLocation = await ts.GetDeviceCurrentLocation();
var latitudeIm = myLocation.Latitude;
var longitudeIm = myLocation.Longitude;
You should decorate all methods as async completely. If you don't able to apply it (I wouldn't recommend it), you could use ConfigureAwait to prevent deadlock;
var position = await locator.GetPositionAsync(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
var myLocation = ts.GetDeviceCurrentLocation().Result;//Also don't hit the Result twice
var latitudeIm = myLocation.Latitude;
var longitudeIm = myLocation.Longitude;