|
int[] num = new int[10]; int input = 0; while (input <= 10)
{
Your int array contains only 10 items but your while loop accepts an index value of 10 which is beyond the array limit.
Change the while loop to
while (input < 10)
|
|
|
|
|
You have to be careful with array indexers. Array indexes always start at 0, not 1.
When you declared an array with int[] num = new int[10]; , you created an array with 10 elements, numbered 0 through 9.
So, when you put the limit expression in your while (input <= 10) , you said the last index in the array was 10, not 9.
|
|
|
|
|
Hope you understand that Index start from 0 and not 1.
So if you have an array of 10 integers, the indices will be 0 ..9.
while (input <= 10)
{
num[input] = Convert.ToInt32(Console.ReadLine());
}
Here While loop will iterate 11 times when input = 0, 1, 2, ..10
when you try to access num[10], you will get an Index out of range .
|
|
|
|
|
I have mapper method which maps different types of property like bool,enum,string,int
But now I want to map my one of the custom class which is being inherited in several places
Back Story:
Earlier we were creating instance and assigning values in POM only, now we want to use Excel to pass value and map and then use in our methods
Object classes Which I want to map
namespace Framework.Model.PaymentOptions
{
public class PaymentOptions
{
public PaymentPortal portal;
public DeliveryMethod delivery = DeliveryMethod.Billing;
public PaymentOptions()
{
}
public PaymentOptions(Site site)
{
}
}
}
Which is inherited in below class
namespace Framework.Model.PaymentOptions
{
public class KlarnaOptions : PaymentOptions
{
public bool byCard = false;
public bool payLater = false;
public bool sliceIt = false;
public KlarnaOptions()
{
portal = PaymentPortal.Klarna;
}
}
}
Earlier we used to access and assign the values as below
Assigning Values
public class WorkflowParameters
{
public Site _site = default(Site);
public PaymentOptions paymentOptions = default(PaymentOptions);
}
var param = new WorkflowParameters()
{
paymentOptions = new KlarnaOptions()
{
delivery = DeliveryMethod.Billing,
payLater = true
}
};
Use in Methods would be as below
Checkout(param.paymentoptions);
Now we want to pass values from Excel Sheet
Mapper Method
public static class PropertyMapHelper
{
public static void Map(Type type, DataRow row, PropertyInfo prop, object entity)
{
List<string> columnNames = AttributeHelper.GetDataNames(type, prop.Name);
foreach (var columnName in columnNames)
{
if (!String.IsNullOrWhiteSpace(columnName) && row.Table.Columns.Contains(columnName))
{
var propertyValue = row[columnName];
if (propertyValue != DBNull.Value)
{
ParsePrimitive(prop, entity, row[columnName]);
break;
}
}
}
}
private static void ParsePrimitive(PropertyInfo prop, object entity, object value)
{
if (prop.PropertyType == typeof(string))
{
prop.SetValue(entity, value.ToString().Trim(), null);
}
else if (prop.PropertyType == typeof(bool) || prop.PropertyType == typeof(bool?))
{
if (value == null)
{
prop.SetValue(entity, null, null);
}
else
{
prop.SetValue(entity, ParseBoolean(value.ToString()), null);
}
}
else if (prop.PropertyType == typeof(long))
{
prop.SetValue(entity, long.Parse(value.ToString()), null);
}
else if (prop.PropertyType == typeof(int) || prop.PropertyType == typeof(int?))
{
if (value == null)
{
prop.SetValue(entity, null, null);
}
else
{
prop.SetValue(entity, int.Parse(value.ToString()), null);
}
}
else if (prop.PropertyType == typeof(decimal))
{
prop.SetValue(entity, decimal.Parse(value.ToString()), null);
}
else if (prop.PropertyType == typeof(double) || prop.PropertyType == typeof(double?))
{
double number;
bool isValid = double.TryParse(value.ToString(), out number);
if (isValid)
{
prop.SetValue(entity, double.Parse(value.ToString()), null);
}
}
else if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(Nullable<DateTime>))
{
DateTime date;
bool isValid = DateTime.TryParse(value.ToString(), out date);
if (isValid)
{
prop.SetValue(entity, date, null);
}
else
{
isValid = DateTime.TryParseExact(value.ToString(), "MMddyyyy", new CultureInfo("en-US"), DateTimeStyles.AssumeLocal, out date);
if (isValid)
{
prop.SetValue(entity, date, null);
}
}
}
else if (prop.PropertyType.IsEnum)
{
var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
var enumValue = Enum.Parse(type, value.ToString(), true);
prop.SetValue(entity, enumValue, null);
}
else if (prop.PropertyType == typeof(Guid))
{
Guid guid;
bool isValid = Guid.TryParse(value.ToString(), out guid);
if (isValid)
{
prop.SetValue(entity, guid, null);
}
else
{
isValid = Guid.TryParseExact(value.ToString(), "B", out guid);
if (isValid)
{
prop.SetValue(entity, guid, null);
}
}
}
else if(prop.PropertyType == typeof(PaymentOptions))
{
}
}
public static bool ParseBoolean(object value)
{
if (value == null || value == DBNull.Value) return false;
switch (value.ToString().ToLowerInvariant())
{
case "1":
case "y":
case "yes":
case "true":
return true;
case "0":
case "n":
case "no":
case "false":
default:
return false;
}
}
}
Test Data Model
namespace Framework.Model.Excel
{
public partial class TestDataModel
{
public TestDataModel() {
}
[DataNames("TestName")]
public string TestName { get; set; }
[DataNames("paymentOptions")]
public PaymentOptions paymentOptions { get; set; }
[DataNames("SiteGroupId")]
public SiteGroup SiteGroupId { get; set; }
[DataNames("NickName")]
public string NickName { get; set; }
[DataNames("byCard")]
public bool byCard { get; set; }
[DataNames("payLater")]
public bool payLater { get; set; }
[DataNames("sliceIt")]
public bool sliceIt { get; set; }
[DataNames("portal")]
public PaymentPortal portal { get; set; }
[DataNames("delivery")]
public DeliveryMethod delivery{get;set;}
}
}
Currently, it is not mapping values of Payment Options, and also I do not know how will I access param.paymentoptions which will have delivery and payLater information
|
|
|
|
|
Before you start - do you have absolute control of the Excel format? If not you are in for a world of pain, you will need to locate the cell the values are in using interop or one of the excel libraries.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
I am mapping excel values to test data model through mapper method, I am not using Interop
|
|
|
|
|
How are you getting the data from Excel?
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
 Here is the function:
public static IList<TestDataModel> GetAllTestData(string keyName)
{
DataSet ds = new DataSet();
DataNamesMapper<TestDataModel> mapper = new DataNamesMapper<TestDataModel>();
DataTable dataTableALL = new DataTable();
List<TestDataModel> testData = new List<TestDataModel>();
using (var connection = new
OdbcConnection(TestDataFileConnection()))
{
connection.Open();
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = connection;
System.Data.DataTable dtSheet = null;
dtSheet = connection.GetSchema(OdbcMetaDataCollectionNames.Tables, null);
foreach (DataRow row in dtSheet.Rows)
{
string sheetName = row["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
var query = string.Format("select * from [{0}] where TestName = '{1}'", sheetName, keyName);
cmd.CommandText = query;
DataTable dt = new DataTable();
dt.TableName = sheetName;
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
cmd = null;
connection.Close();
}
DataTable data= JoinExcelDatatoOneRow(ds);
testData = mapper.Map(data).ToList();
return testData.ToList();
}
|
|
|
|
|
So your data is coming in via ODBC which leaves you with a datatable. Make sure the source datatable has the same names as the destination object. Presumably excel does not have the payment options in the source so you need to load the default into the excel result set, simply return the default instead of the get/set property.
If Excel has the paymentoptions then it may be a complex type and will need specific processing to assign multiple values into your target object
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
So, if I browse to my site and login, I get a page with my personal images.
For example, I'm on-site with a client, take pictures, login and upload them. I want to retrieve them automatically from my laptop. To do so automatically, I need to login, get the HTML, grab the links then use WebClient.DownloadFile. Problem is, I can't see the HTML without a browser.
SO, more specifically - When I login with a browser and right click and "view HTML" I don't see the images in the markup, just the header and the footer HTML. The ONLY way to see the source is to use the inspector tool by right clicking on one of the images. So this code is generated by the browser, but not part of the original request.
I wrote a C# app that will log into my page and it works. I can login via SSL and my credentials, navigate pages BUT ... I can't see all the HTML.
I added a WebView2 form to my project (new Edge browser plugin for VS) and I can see the page, but I STILL can't get the source to get the path to the image.
So is there a way to get at this generated HTML programatically in C#? I can launch the dev tools (inspector) window with
myWebView2Browser.CoreWebView2.OpenDevToolsWindow(); ... but I need a way to view the ELEMENTS tab in that tool where the true HTML is.
I tried
myHTML = await myWebView2Browser.ExecuteScriptAsync("document.documentElement.outerHTML;"); ... and it gets the HTML, but NOT the FINAL rendered HTML that I can see in the inspector.
Hope this makes sense, it's making me crazy being so close! Thanks in advance!
|
|
|
|
|
Ask yourself - where are the images stored when I upload them?
They will either be in a database or the file system on the server. Instead of trying to use the HTML to get the file go directly to the source and download them from there, you should already have the credentials to access the server.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
What you're looking for is called a headless browser, so google "c# headless browser". However I agree that if you can simply download the images directly that would be better.
|
|
|
|
|
While I was reading code produced by coworker of mine, I got confused.
What does
public void DoSomething(double someParameter)
{
_SomeComponent.Set(someParameter);
Task.Run(() => Check(someParameter)).Wait();
} actually do, i.e. how does it differ from
public void DoSomething(double someParameter)
{
_SomeComponent.Set(someParameter);
Check(someParameter);
} The Check function is synchronous. So, the two versions could be equivalent?
That Task.Run starts the Check function in a new Task . But because of the Wait , DoSomething won't be left immediately after starting that Task , but only when that Task ran to completion (or failure).
But I am too confused by that snippet now to be sure of my assumptions.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
Bernhard Hiller wrote: how does it differ from
Well, it uses more memory, and adds a thread to the system ...
But no, you are right. In essence starting a Task to call Check and then calling Wait is the same as calling the method directly: the calling method will not continue until Check is complete.
It's possible that the cow-orker doesn't know what he is doing, it's possible that the Check method was used elsewhere and called via a Task without the Wait, but that code caused problems when re-used. We don't know, and will probably never find out.
But it's pretty poor code in it's current form!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thanks.
When you say that the cow-orker did not know what he did, you may be right. Next to that code sits a TimeSpan.FromSeconds(SET_XY_MAX_WAIT_TIME_MS) (seconds vs. implied milliseconds ms)...
Or he just tries to obfuscate his code so that nobody else can deal with it - job security by obscurity!
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
GO to QA - you'll meet a lot of that!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Is it possible that there are other tasks / threads and the author is trying to allow them to have a turn?
|
|
|
|
|
Hi all, just revisiting some code that scans a local LAN for servers broadcasting on UDP port 3483 and I'm seeing strange characters in the response string when I run the code on Win 10
I expect
"ENAME0\LMSPi\JSON0\9000"
but I'm getting
"ENAME\u0005LMSPi0JSON\u00049000"
I'm sure the weren't there when I ran the code under Win 7
What I'm after is the port number the server is running on which is the 9000 after JSON ( without the u0004 )
Any idea why I'm seeing these characters ?
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace LMS
{
class ScanLAN
{
[STAThread]
static int Main()
{
ScanForServer();
return 0;
}
static void ScanForServer()
{
IPEndPoint ReceiveIP = null;
UdpClient listener = null;
Byte[] RequestData = null;
byte[] BytesReceived = null;
string RetVal = "No response from LAN";
int UDPPort = 3483;
try
{
Console.WriteLine($"Starting LAN broadcast on port {UDPPort}...");
ReceiveIP = new IPEndPoint(IPAddress.Any, UDPPort);
listener = new UdpClient(UDPPort);
RequestData = listener.Receive(ref ReceiveIP);
if (RequestData != null && RequestData.Length > 0)
RetVal = Encoding.UTF8.GetString(RequestData);
Console.WriteLine($"Initial response data {RetVal}");
listener.Send(RequestData, RequestData.Length, ReceiveIP);
BytesReceived = listener.Receive(ref ReceiveIP);
if (BytesReceived != null && BytesReceived.Length > 0)
RetVal = Encoding.UTF8.GetString(BytesReceived);
Console.WriteLine($"Final response data {RetVal}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (listener != null && listener.Client.Connected)
listener.Close();
}
}
}
}
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
|
|
|
|
|
There seems to be an encoding problem.
The MSDN examples on UdpClient.Receive all use Encoding.ASCII.GetString, whereas your code uses Encoding.UTF8
Also when I run
string s1= "ENAME\u0005LMSPi0JSON\u00049000";
byte[] bytes=Encoding.UTF8.GetBytes(s1);
string s2 = Encoding.ASCII.GetString(bytes);
then s2 looks almost identical to what you expected.
If this would be the solution, then I can't explain why it worked well on Win7.
Beware, code working well does not imply code being correct...
|
|
|
|
|
Thanks Luc I'll give it a shot
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
|
|
|
|
|
Hi Luc, I tried it with ASCII and no different I'll show you the entire string this time ( I abridged it in the original post )
"ENAME\u0005LMSPiJSON\u00049000UUID$0b5a576d-a276-4920-a9e8-134c41133102VERS\u00057.9.2"
Breaking it down
ENAME = LMSPi -- my server hostname
JSON = 9000 -- my server port
UUID = self explanatory
VERS = software version
If I print the byte array one byte at a time and convert it to a char I get
for (int i = 0; i < BytesReceived.Length; ++i)
{
char x = (char)BytesReceived[i];
Console.Write(x);
}
ENAMELMSPiJSON9000UUID$0b5a576d-a276-4920-a9e8-134c41133102VERS7.9.2
which is more like what I expect
Thanks very much for your help
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
modified 1-Jul-20 13:28pm.
|
|
|
|
|
So it is a series of key-value pairs, where each value (except the GUID that has a fixed length) would need either a length or a separator; in this case a length is used, i.e. the 6 characters "\u000X" stand for a the length of X for the value that follows; normally a small length could be stored in a single byte.
As you receive the lengths in this escape format no matter what encoding is used to receive them (so you told me), it suggests something might be wrong at the transmitter, not the receiver.
ALERT
Wait a minute, where are you seeing those unexpected strings exactly?
You are aware Visual Studio sometimes uses escapes, quotes, etc in its immediate window and maybe elsewhere too. Use Console.WriteLine to make sure, and/or apply string.Length and count the characters manually to compare!!!
modified 5-Jul-20 9:29am.
|
|
|
|
|
Hi Luc it was VS misleading me here is what I ended up doing to parse the values
Response from server - there are non printable characters in the response which I can't get to display here which contain the data lengths
ENAMELMSPiJSON9000UUID$0b5a576d-a276-4920-a9e8-134c41133102VERS7.9.2;
ResponseColumn ParseResponseString(string FieldName,string ResponseString)
{
ResponseColumn rc = new ResponseColumn();
int pos = ResponseString.IndexOf(FieldName);
string ColumnName = ResponseString.Substring(pos,5);
int DataLen = Convert.ToInt32(ColumnName[4]);
pos+= 5;
string ColumnValue = ResponseString.Substring(pos,DataLen);
rc.ColumnName = FieldName;
rc.ColumnValue = ColumnValue;
return rc;
}
public class ResponseColumn
{
public string ColumnName {get;set;}
public string ColumnValue{get;set;}
}
and use it thus
ResponseColumn rcPortNumber = ParseResponseString("JSON",ResponseString);
ResponseColumn rcServerName = ParseResponseString("NAME",ResponseString);
ResponseColumn rcServerVer = ParseResponseString("VERS",ResponseString);
Thanks for all your help
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
modified 2-Jul-20 7:34am.
|
|
|
|
|
You're welcome.
Two comments though:
1. you completely replaced the content of this message; I got an e-mail when you first created it. And obviously not when you replaced all of it, so it took a while before I accidentally noticed the new content. You should not replace/delete messages on CodeProject, you can create new ones, or add to or slightly edit existing ones.
2. your code is fine with the current data. It has a few weaknesses in general: it assumes field names are always 4 chars (see constants 4 and 5), and it locates field names by a string search, which could go wrong when one field name happens to appear as (part of) another field's value.
The universal way to handle this would be to scan the entire line and build a Dictionary<string,string> holding all the key-value pairs in the line; that too would rely on some restrictions on field names and/or values (e.g. field names are uppercase letters only, and field value lengths must be less than 'A').
Cheers
modified 5-Jul-20 9:45am.
|
|
|
|
|
Hi Luc, just some answers to your observations
it assumes field names are always 4 chars
they have been 4 chars for the last 25 years
and it locates field names by a string search,
How else could it be done ?
which could go wrong when one field name happens to appear as (part of) another field's value.
The fields always end with a data length
Thanks again
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
modified 6-Jul-20 4:27am.
|
|
|
|
|