How to insert a large image into an SQL database - asp.net-core

If I insert a small image, for example 1-2 kb, then it is successful, if I select an image of 70 kb or any other large one, then I always have an error.
I have tried both the stored procedure and directly pass an array of bytes - error.
Exception System.Data.SqlClient.SQLException: "A transport layer error occurred while receiving results from the server. (provider: TCP provider, error: 0 - The semaphore timeout is exceeded.)"
Everything is fine with SQL Server itself, images are loaded successfully through WinForms, there are no problems.
Button:
<RadzenUpload Accept="image/*" ChooseText="Select..." Url=#($"api/upload/single/{clientid}/1") Progress="#((args) => OnProgress(args, "Loading ..."))" />
Controller and void:
[HttpPost("single/{id}/{photoid}")]
public async Task<IActionResult> Single(IFormFile file, string id,string photoid)
{
try
{
IVZBlazor.Iservice.IPhotoService serv;
string fileName = Path.GetFileName(file.FileName);
string rootpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot");
string path = rootpath + "\\Uploads";
using var fileStream = file.OpenReadStream();
long length = file.Length;
byte[] bytes = new byte[length];
fileStream.Read(bytes, 0, (int)file.Length);
using (FileStream stream = new FileStream(Path.Combine(path, fileName), FileMode.Create))
{
file.CopyTo(stream);
}
await Save(bytes, id);
return StatusCode(200);
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
private DynamicParameters SetParameter(byte[] oPhoto)
{
DynamicParameters parameters = new DynamicParameters();
parameters.Add("#photo", oPhoto);
return parameters;
}
public async Task<int> Save(byte[] photo, string clientid)
{
using (var connection = new SqlConnection(Startup.ConnectSQL))
{
await connection.OpenAsync();
var sqlStatement = #"UPDATE [dbo].[photo] SET [image1] =#photo WHERE [personid] ='" + clientid + "'";
int res = await connection.ExecuteAsync(sqlStatement, SetParameter(photo));
return res;
}
}

Related

ASP .Net Core file upload - getting form data when [DisableFormValueModelBinding] attribute is in place

I went ahead and implemented an ASP .Net Core file upload controller per the documentation and it requires using a [DisableFormValueModelBinding] attribute for streaming large files. I got that working fine. Unfortunately, when using that attribute it seems to block my JSON properties coming in from the form.
Is there any way to get both the file and the form data here? Here is my controller code (the request.form calls are where I am having issues):
[Route("{caseNbr:int}/Document")]
[ResponseType(typeof(CaseDocumentModel))]
[DisableFormValueModelBinding]
[HttpPost]
public async Task<IActionResult> PostDocument(int caseNbr)
{
string errorTrackingFileName = string.Empty;
try
{
UserSessionModel userSessionModel = SessionExtensions.CurrentUserSession;
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest("Bad Request");
}
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
return BadRequest("Bad Request");
}
var fileName = WebUtility.HtmlEncode(contentDisposition.FileName.Value);
errorTrackingFileName = fileName;
var trustedFileNameForFileStorage = fileName; //Path.GetRandomFileName();
var streamedFileContent = await FileHelpers.ProcessStreamedFile(section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit);
if (!ModelState.IsValid)
{
return BadRequest("Bad Request");
}
using (var targetStream = System.IO.File.Create(Path.Combine(_tempFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);
**//This is where I am having trouble:**
string descrip = HttpContext.Request.Form["Description"].ToString();
string docType = HttpContext.Request.Form["DocType"].ToString() ?? "Document";
bool isGeneralFileUpload = false;
if (string.IsNullOrWhiteSpace(Request.Form["GeneralFileUpload"]) == false && AppHelper.IsBool(Request.Form["GeneralFileUpload"]))
isGeneralFileUpload = bool.Parse(Request.Form["GeneralFileUpload"]);
int transcriptionJobId = 0;
if (string.IsNullOrWhiteSpace(Request.Form["TranscriptionJobId"]) == false && AppHelper.IsNumeric(Request.Form["TranscriptionJobId"]))
transcriptionJobId = int.Parse(Request.Form["TranscriptionJobId"]);
CaseDocumentModel createdCaseDocumentModel;
if (docType.Equals("Dictation"))
createdCaseDocumentModel = DictationRepository.ProcessDictationFile(userSessionModel.DBID, caseNbr, _tempFilePath, fileName, userSessionModel);
else if (isGeneralFileUpload)
createdCaseDocumentModel = DashboardAdjusterRepository.CreateGeneralFileUploadDocument(_tempFilePath, fileName, userSessionModel, docType, descrip);
else if (docType.Equals("Transcription"))
createdCaseDocumentModel = TranscriptionRepository.UploadTranscriptionFile(userSessionModel.DBID, _tempFilePath, fileName, userSessionModel, transcriptionJobId);
else
createdCaseDocumentModel = CaseRepository.CreateCaseDocumentRecord(userSessionModel.DBID, caseNbr, descrip, docType, _tempFilePath, fileName, userSessionModel);
return Ok(createdCaseDocumentModel);
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
}
catch (Exception ex)
{
AppHelper.WriteErrorLog("CaseController PostDocument failed due to " + ex.Message + " case number was " + caseNbr + " file name was " + errorTrackingFileName);
return BadRequest("Bad Request");
}
return BadRequest("Bad Request");
}
Here is a sample call with Postman:
Screen shot of Postman

Azure Logic Apps internal server error 500

Am trying to create a an azure function that is triggered in a Logic Apps,
The functions purpose is to web crawl certain web sites, take the desired information, compare that with a a SQL Server database in Azure, compare if we already have that information if not add it.
My issue is that when ever i run it I get the Server 500 error, I assume its accessing the database that cause. Help?
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log
)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string RequestBody = await new StreamReader(req.Body).ReadToEndAsync();
{
return await CrawlBlog(0, RequestBody);
}
}
private static async Task<IActionResult> CrawlBlog(int Picker, string req)
{
int BlogPicker = Picker;
string TheResult = req;
//Get the url we want to test
var Url = "";
if (BlogPicker == 0)
{
Url = "*********";
}
else if (BlogPicker == 1)
{
Url = "*********";
}
/*
else if (BlogPicker == 2)
{
Url = "https://azure.microsoft.com/en-in/blog/?utm_source=devglan";
}
*/
else
{
TheResult = "False we got a wrong pick";
return (ActionResult)new OkObjectResult
( new {TheResult });
}
var httpClient = new HttpClient();
var html = await httpClient.GetStringAsync(Url);
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(html);
//a list to add all availabel blogs we found
var Blog = new List<BlogStats>();
switch (BlogPicker)
{
case 0:
{
var divs =
htmlDocument.DocumentNode.Descendants("div")
.Where(node => node.GetAttributeValue("class", "").Equals("home_blog_sec_text")).ToList();
foreach (var divo in divs)
{
var Blogo = new BlogStats
{
Summary = divo.Descendants("p").FirstOrDefault().InnerText,
Link = divo.Descendants("a").FirstOrDefault().ChildAttributes("href").FirstOrDefault().Value,
Title = divo.Descendants("a").FirstOrDefault().InnerText
};
Blog.Add(Blogo);
}
break;
}
case 1:
{
var divs =
htmlDocument.DocumentNode.Descendants("div")
.Where(node => node.GetAttributeValue("class", "").Equals("post_header_title two_third last")).ToList();
foreach (var divo in divs)
{
//string TheSummary = "we goofed";
var ThePs = divo.Descendants("p").ToList();
var Blogo = new BlogStats
{
Summary = ThePs[1].GetDirectInnerText(),
Link = divo.Descendants("a").LastOrDefault().ChildAttributes("href").FirstOrDefault().Value,
Title = divo.Descendants("a").FirstOrDefault().InnerText
};
Blog.Add(Blogo);
}
break;
}
}
TheResult = await SqlCheck(Blog[0].Title, Blog[0].Summary, Blog[0].Link); //error 500
return (ActionResult)new OkObjectResult
(
new
{
TheResult
}
);
}
public static async Task<string> SqlCheck(string Tit, string Sumy, string Lin)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "flygon.database.windows.net";
builder.UserID = "*****";
builder.Password = "********";
builder.InitialCatalog = "torkoal";
System.Data.DataSet ds = new System.Data.DataSet();
SqlConnection connection = new SqlConnection(builder.ConnectionString);
connection.Open();
SqlCommand CheckCommand = new SqlCommand("SELECT * FROM TableBoto WHERE Link = #id3 ", connection);
CheckCommand.Parameters.AddWithValue("#id3", Lin);
SqlDataAdapter dataAdapter = new SqlDataAdapter(CheckCommand);
dataAdapter.Fill(ds);
int i = ds.Tables[0].Rows.Count;
if (i > 0)
{
return $" We got a Duplicates in title : {Tit}";
}
try
{
{
string query = $"insert into TableBoto(Title,Summary,Link) values('{Tit}','{Sumy}','{Lin}');";
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = await command.ExecuteReaderAsync();
reader.Close();
}
}
catch (SqlException)
{
// Console.WriteLine(e.ToString());
}
connection.Close();
return $" Success Ign +{Tit} + Ign {Sumy}+ Ign {Lin} Ign Success SQL ";
}
}
500 HTTP status code is a generic code which means that the server was not able to process the request due to some issues, First step would be to add some exception handling to your function and see if the failure occurs and where it occurs.
On Side note, you should not use HTTP client in the way used in the code, you should not new it up every time your function executes, this client should be static in nature. Refer Manage connections in Azure Functions

Uploading Large Files to Azure Blob Storage throwing Exception

I have a scenario to upload databases backups to the Azure Blob storage via Window Service.
It is working for the bak files size range between 300-500 MB but if the size exceeds 700 MB to 1 GB or more. It took more than an hour and then throw an exception.
Please check the code below let me know what I am doing wrong and what is the efficient method to upload large size files to blob storage. I have tried these two methods.
public static void UploadFile(AzureOperationHelper azureOperationHelper)
{
CloudBlobContainer blobContainer = CreateCloudBlobContainer(tenantId, applicationId,
clientSecret, azureOperationHelper.storageAccountName, azureOperationHelper.containerName,
azureOperationHelper.storageEndPoint);
blobContainer.CreateIfNotExists();
var writeOptions = new BlobRequestOptions()
{
SingleBlobUploadThresholdInBytes = 50 * 1024 * 1024,//maximum for 64MB,32MB by default
ParallelOperationThreadCount = 12,
};
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(azureOperationHelper.blobName);
//blob.UploadFromFile(azureOperationHelper.srcPath);
blob.UploadFromFile(azureOperationHelper.srcPath, options: writeOptions);
}
public static void UploadFileStream(AzureOperationHelper azureOperationHelper)
{
CloudBlobContainer blobContainer = CreateCloudBlobContainer(tenantId, applicationId,
clientSecret, azureOperationHelper.storageAccountName, azureOperationHelper.containerName,
azureOperationHelper.storageEndPoint);
blobContainer.CreateIfNotExists();
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(azureOperationHelper.blobName);
//byte[] contents = File.ReadAllBytes(azureOperationHelper.srcPath);
//var writeOptions = new BlobRequestOptions()
//{
// SingleBlobUploadThresholdInBytes = 50 * 1024 * 1024,//maximum for 64MB,32MB by default
// ParallelOperationThreadCount = 12,
//};
//blob.UploadFromByteArray(contents, 0, contents.Length, AccessCondition.GenerateIfNotExistsCondition(), options: writeOptions);
blob.StreamWriteSizeInBytes = 100 * 1024 * 1024; //100 MB
blob.UploadFromFile(string.Format(azureOperationHelper.srcPath));
//using (var fs = new FileStream(azureOperationHelper.srcPath, FileMode.Open))
//{
// blob.UploadFromStream(fs);
//}
}
Below are the exceptions I got.
Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: (403) Forbidden. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden. at Microsoft.WindowsAzure.Storage.Shared.Protocol.HttpResponseParsers.ProcessExpectedStatusCodeNoException[T](HttpStatusCode expectedStatusCode, HttpStatusCode actualStatusCode, T retVal, StorageCommandBase`1 cmd, Exception ex)
Microsoft.WindowsAzure.Storage.StorageException: The client could not finish the operation within specified timeout. ---> System.TimeoutException: The client could not finish the operation within specified timeout.
Please the code below, it works well at my side(about 2GB file, takes about 10 minutes for completing uploading):
public string UploadFile(string sourceFilePath)
{
try
{
string storageAccountConnectionString = "AZURE_CONNECTION_STRING";
CloudStorageAccount StorageAccount = CloudStorageAccount.Parse(storageAccountConnectionString);
CloudBlobClient BlobClient = StorageAccount.CreateCloudBlobClient();
CloudBlobContainer Container = BlobClient.GetContainerReference("container-name");
Container.CreateIfNotExists();
CloudBlockBlob blob = Container.GetBlockBlobReference( Path.GetFileName(sourceFilePath) );
HashSet<string> blocklist = new HashSet<string>();
byte[] fileContent = File.ReadAllBytes(sourceFilePath);
const int pageSizeInBytes = 10485760;
long prevLastByte = 0;
long bytesRemain = fileContent.Length;
do
{
long bytesToCopy = Math.Min(bytesRemain, pageSizeInBytes);
byte[] bytesToSend = new byte[bytesToCopy];
Array.Copy(fileContent, prevLastByte, bytesToSend, 0, bytesToCopy);
prevLastByte += bytesToCopy;
bytesRemain -= bytesToCopy;
//create blockId
string blockId = Guid.NewGuid().ToString();
string base64BlockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId));
blob.PutBlock(
base64BlockId,
new MemoryStream(bytesToSend, true),
null
);
blocklist.Add(base64BlockId);
} while (bytesRemain > 0);
//post blocklist
blob.PutBlockList(blocklist);
return "Success";
}
catch (Exception ex)
{
return ex.Message;
}
}
It works well for uploading large file(someone gives the solution from here).
Please let me know if you can work with it.

Win Phone 8.1 : OutOfMemory Exception while downloading large files (30 MB)

I am creating a universal Windows Phone 8.1 App. I am trying to download the file and view it into launcher. I works for small file less than 15 MB files. But when file size is more than 15 MB, I got the out of memory exception.
async private Task<object> GetMailAttachments(string attachNotify)
{
try
{
cmdBarMailItem.IsEnabled = false;
if (await Device.IsNetworkAvailable())
{
cts = new CancellationTokenSource();
// Ignore SSL Certificate which is untrusted,expired and has invalid hostname.
var filter = new HttpBaseProtocolFilter() { AllowUI = false };
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.InvalidName);
// Start calling the soap service #userGetAttachmentByIndex
using (var client = new System.Net.Http.HttpClient(new WinRtHttpClientHandler(filter)))
{
//Prepare parameters which is to be post via soap envelope.
List<KeyValuePair<string, string>> parameter = new List<KeyValuePair<string, string>>();
parameter.Add(new KeyValuePair<string, string>("sessionId", GlobalInfo.SessionID));
parameter.Add(new KeyValuePair<string, string>("attachmentIndex", attachNotify.Split('|')[1].ToString()));
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
client.DefaultRequestHeaders.Add("SOAPAction", "userGetAttachmentByIndex");
var postContent = new StringContent(StringHelper.ConstructSoapRequest(parameter, "userGetAttachmentByIndex"), Encoding.UTF8, "text/xml");
// Getting response from soap service
var response = await client.PostAsync(new Uri(AppEnv.ServiceEndPoint), postContent, cts.Token);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string soapResponse = await response.Content.ReadAsStringAsync();
var soap = XDocument.Parse(soapResponse);
XNamespace ns = "http://service.webservice.cryoserver.ci";
var base64BinaryStr = soap.Descendants(ns + "userGetAttachmentByIndexResponse").First().Descendants(ns + "return").First().Descendants(ns + "attachmentType").First().Descendants(ns + "binaryData").First().Descendants(ns + "base64Binary").First().Value;
await saveStringToLocalFile(base64BinaryStr);
var file = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("myTest.pdf");
bool x = await Windows.System.Launcher.LaunchFileAsync(file);
return x;
}
}
}
cmdBarMailItem.IsEnabled = true;
}
catch (TaskCanceledException)
{
PopupRetrieve.IsOpen = false;
ProgressBar.IsVisible = false;
cmdBarMailItem.IsEnabled = true;
}
catch(Exception ex)
{
cmdBarMailItem.IsEnabled = true;
ProgressBar.IsVisible = false;
MessageBox.Show(AlertType.Connectivity);
}
return null;
}
async Task saveStringToLocalFile(string content)
{
try
{
// saves the string 'content' to a file 'filename' in the app's local storage folder
// byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(content.ToCharArray());
byte[] byteArray = Convert.FromBase64String(content);
// create a file with the given filename in the local folder; replace any existing file with the same name
StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("myTest.pdf", CreationCollisionOption.ReplaceExisting);
// write the char array created from the content string into the file
using (var stream = await file.OpenStreamForWriteAsync())
{
stream.Write(byteArray, 0, byteArray.Length);
stream.Flush();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I got the exception on executing the line
string soapResponse = await response.Content.ReadAsStringAsync();
Anybody have an idea why the exception occurs ? What could be possible solution to fix it.
Any help would be appriciable. :)

Why am I getting, "Unable to connect to the remote server"?

This err msg is the next one I get after resolving “NotSupportedException” as noted here
I don't even reach the break point in the server code (set on the first line of the method that should be getting called).
This is the relevant server code:
[Route("api/PlatypusItems/PostArgsAndXMLFileAsStr")]
public async void PostArgsAndXMLFileAsStr([FromBody] string stringifiedXML, string serialNum, string siteNum)
{
string beginningInvoiceNum = string.Empty; // <= Breakpoint on this line
string endingInvoiceNum = string.Empty;
XDocument doc = XDocument.Load(await Request.Content.ReadAsStreamAsync());
. . .
And the client (handheld, Compact Framework) code:
private void menuItem4_Click(object sender, EventArgs e)
{
GetAndSendXMLFiles("LocateNLaunch"); // There is a "LocateNLaunch.xml" file
}
private void GetAndSendXMLFiles(string fileType)
{
string serNum = User.getSerialNo();
string siteNum = User.getSiteNo();
if (serNum.Length == 0)
{
serNum = "8675309";
}
if (siteNum.Length == 0)
{
siteNum = "03";
}
string uri = string.Format("http://localhost:28642/api/PlatypusItems/PostArgsAndXMLFileAsStr?serialNum={0}&siteNum={1}", serNum, siteNum);
List<String> XMLFiles = HHSUtils.GetXMLFiles(fileType, #"\");
MessageBox.Show(XMLFiles.Count.ToString());
foreach (string fullXMLFilePath in XMLFiles)
{
MessageBox.Show(fullXMLFilePath);
RESTfulMethods.SendXMLFile(fullXMLFilePath, uri, 500);
}
}
public static string SendXMLFile(string xmlFilepath, string uri, int timeout) // timeout should be 500
{
MessageBox.Show(string.Format("In SendXMLFile() - xmlFilepath == {0}", xmlFilepath));
MessageBox.Show(string.Format("In SendXMLFile() - uri == {0}", uri));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(xmlFilepath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());
if (timeout < 0)
{
request.ReadWriteTimeout = timeout;
request.Timeout = timeout;
}
request.ContentLength = postBytes.Length;
request.KeepAlive = false;
request.ContentType = "application/xml";
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
return response.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show("SendXMLFile exception " + ex.Message);
request.Abort();
return string.Empty;
}
}
}
Running this code, I see from the client the following "debug strings":
0) "1" (from MessageBox.Show(XMLFiles.Count.ToString());)
1) "\Program Files\LocateNLaunch\LocateNLaunch.xml" (from MessageBox.Show(fullXMLFilePath);)
2) "In SendXMLFile() - xmlFilePath == \Program Files\LocateNLaunch\LocateNLaunch.xml" (from MessageBox.Show(string.Format("In SendXMLFile() - xmlFilepath == {0}", xmlFilepath));)
3) "In SendXMLFile() - uri == http://localhost:28642/api/PlatypusItems/PostArgsAndXMLFileAsStr?serialNum=8675309&siteNum=03" (from MessageBox.Show(string.Format("In SendXMLFile() - uri == {0}", uri));)
- and then this one from somewhere:
4) "SendXMLFile exception Unable to connect to the remote server"...
So what could be causing this inability to connect?
UPDATE
The same thing ("Unable to Connect to the Remote Server") happens with this code (different operation, but also from the WindowsCE/Compact Framework/handheld app that tries to connect to the Web API server app):
private void menuItem3_Click(object sender, EventArgs e)
{
string serNum = User.getSerialNo();
if (serNum.Length == 0)
{
serNum = "8675309";
}
string clientVer =
HHSUtils.GetFileVersion(#"\Application\sscs\vsd_setup.dll");
if (clientVer.Contains("Win32Exception"))
{
clientVer = "0.0.0.0";
}
MessageBox.Show(string.Format("After call to GetFileVersion(), serial num == {0};
clientVer == {1}", serNum, clientVer));
string uri =
string.Format("http://localhost:28642/api/FileTransfer/GetHHSetupUpdate?
serialNum={0}&clientVersion={1}", serNum, clientVer);
RESTfulMethods.DownloadNewerVersionOfHHSetup(uri);
}
public static void DownloadNewerVersionOfHHSetup(string uri)
{
string dateElements = DateTime.Now.ToString("yyyyMMddHHmmssfff",
CultureInfo.InvariantCulture);
var outputFileName = string.Format("HHSetup_{0}.exe", dateElements);
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
string statusCode = webResponse.StatusCode.ToString();
if (statusCode == "NoContent")
{
MessageBox.Show("You already have the newest available version.");
}
else
{
var responseStream = webResponse.GetResponseStream();
using (Stream file = File.Create(outputFileName))
{
CopyStream(responseStream, file);
MessageBox.Show(string.Format("New version downloaded to {0}",
outputFileName));
}
}
}
catch (WebException webex)
{
MessageBox.Show("DownloadNewerVersionOfHHSetup: " + webex.Message);
}
}
// I see the "After call to GetFileVersion()" message in menuItem3_Click() handler, but then "DownloadNewerVersionOfHHSetup: Unable to Connect to the Remote Server" in DownloadNewerVersionOfHHSetup()
And yes, the server app is running.
UPDATE 2
Here is the code that I tested prior to "dumbing it down" (retrofitting it, making it as similar as possible to this working test code, yet that may not be saying much) for Compact Framework:
Client code:
DownloadTheFile(textBoxFinalURI.Text); // with textBoxFinalURI.Text being
"http://localhost:28642/api/FileTransfer/GetUpdatedHHSetup?
serialNum=8675309&clientVersion=1.3.3.3" and the file on the server being
version 1.4.0.15
private void DownloadTheFile(string uri)
{
var outputFileName = "Whatever.exe";
try
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
string statusCode = webResponse.StatusCode.ToString();
if (statusCode == "NoContent")
{
MessageBox.Show("You already have the newest available version.");
}
else
{
var responseStream = webResponse.GetResponseStream();
using (Stream file = File.Create(outputFileName))
{
CopyStream(responseStream, file);
MessageBox.Show(string.Format("New version downloaded to {0}",
outputFileName));
}
}
}
catch (WebException webex)
{
MessageBox.Show(webex.Message);
}
}
Server code:
public HttpResponseMessage GetHHSetupUpdate(string serialNum, string clientVersion)
{
HttpResponseMessage result;
string filePath = GetAvailableUpdateForCustomer(serialNum);
FileVersionInfo currentVersion = FileVersionInfo.GetVersionInfo(filePath);
if (!ServerFileIsNewer(clientVersion, currentVersion))
{
result = new HttpResponseMessage(HttpStatusCode.NoContent);
}
else
{
result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(filePath, FileMode.Open);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
}
return result;
}
private string GetAvailableUpdateForCustomer(string serialNum)
{
if (serialNum == "8675309")
{
return HostingEnvironment.MapPath(#"~\App_Data\HHSetup.exe");
}
else
{
return HostingEnvironment.MapPath(#"~\App_Data\HDP.exe");
}
}
// clientFileVersion is expected to be something like "1.4.0.15"
private bool ServerFileIsNewer(string clientFileVersion, FileVersionInfo serverFile)
{
Version client = new Version(clientFileVersion);
Version server = new Version(string.Format("{0}.{1}.{2}.{3}",
serverFile.FileMajorPart, serverFile.FileMinorPart,
serverFile.FileBuildPart, serverFile.FilePrivatePart));
return server > client;
}
... This code works fine (server code is the same; the client code has been "retrofied")
I can't use the code as-is because of the limitations of Compact Framework / Windows CE. As the title of this post makes clear, I'm not even able to connect to the server from there yet. Is it possible? If so, what needs to change in my client code (not the client code in Update 2, which works in newer versions of .NET, but the client code shown prior to there)?
It's a similar story with the other method that is also returning "Unable to connect to the remote server" - it works fine in "modern" code running in a test app, but once it's retrofitted (better word than refactored when "dumbing down" to Compact Frameworkerize the code).
UPDATE 3
I tried to get more info from the err msg with the code below (old line commented out), but this "rewards" me instead with a NullReferenceException:
catch (WebException webex)
{
//MessageBox.Show("DownloadNewerVersionOfHHSetup: " + webex.Message);
string msg = webex.Message;
string innerEx = webex.InnerException.ToString();
string resp = webex.Response.ToString();
string stackTrace = webex.StackTrace;
string status = webex.Status.ToString();
MessageBox.Show(
string.Format("Message: {0}; Inner Exception: {1}; Response: {2}; Stack Trace: {3}; Status: {4}", msg, innerEx, resp, stackTrace, status));
}
UPDATE 4
As I continued to get NREs, I commented out each subsequent line, one-by-one, until I now have this that runs:
//string innerEx = webex.InnerException.ToString();
//string resp = webex.Response.ToString();
//string stackTrace = webex.StackTrace;
string status = webex.Status.ToString();
MessageBox.Show(
//string.Format("Message: {0}; Inner Exception: {1}; Response: {2}; Stack Trace: {3}; Status: {4}", msg, innerEx, resp, stackTrace, status));
//string.Format("Message: {0}; Response: {1}; Stack Trace: {2}; Status: {3}", msg, resp, stackTrace, status));
//string.Format("Message: {0}; Stack Trace: {1}; Status: {2}", msg, stackTrace, status));
string.Format("Message: {0}; Status: {1}", msg, status));
...but all I get from it is Status of "ConnectFailure" (I already knew that).
UPDATE 5
This runs without an NRE:
string msg = webex.Message;
string innerEx = webex.InnerException.ToString();
string status = webex.Status.ToString();
MessageBox.Show(string.Format("Message: {0}; Status: {1}; inner Ex: {2}", msg, status, innerEx));
And this is what I see:
So why would the server actively refuse the connection?
BTW, ASAP I'm going to bountify this question, or will bountify the answerer after the fact*, with a bounty that would make even Long John Silver and Perro-Negro's eyes glimmer and gleam (cared they for geekCoin, that is).
For facts leading to the arrest and eviction of this bug.
PSYCHE! I changed my mind/there's been a mutiny on the bounty => the bountification will happen here instead.
UPDATE 6
This also (using the "raw" IP Address of the server machine) gives me an NRE:
string uri = string.Format("http://192.168.125.50:28642/api/FileTransfer/GetHHSetupUpdate?serialNum={0}&clientVersion={1}", serNum, clientVer);
...as does using the "friendly name" ("Platypus") of the machine in place of the IP Address.
The large problem I see here is the fact that you have localhost as your address. That's absolutely wrong. localhost means, effectively, "on the same machine as I am running" so unless you've somehow managed to get a async .NET 4.0 web service to run on your Windows CE device and your server code is running there, then this is most certainly not what you want.
If you're running on an emulator, it's still wrong. The emulator is, for all intents and purposes, a separate machine.
You must use the address of the server/PC where that web service is running. It must be a routable address, meaning if you're connected over USB then it's probably ppp_peer and not an IP address (well it resolves to a private address, but the name is easier to remember).