C#: CommandLineParser How to parse URL? [duplicate] - c#

This question already has answers here:
Get URL parameters from a string in .NET
(17 answers)
Closed 6 days ago.
I am working on a C# project which basically works on commands to perform certain operations. It uses CommandLineParser library to parse all these commands and respective argument.
As per the new business requirement, I need to parse an URL which contains verb and parameters.
Is there any built-in/easy way to parse URL in CommandLineParser library,
that will avoid writing custom logic which I explained in below
approach?
Here is my approach to solve this challenge:
Covert URL to command, then using CommandLine parser assign values to option properties.
e.g.
URL:
https://localhost:9000/Open?appId=123&appName=paint&uId=511a3434-37e0-4600-ab09-65728ac4d8fe
Implementation:
Custom logic to covert url to command
open -appId 123 -name paint -uid 511a3434-37e0-4600-ab09-65728ac4d8fe
Then pass it to parser.ParseArguments
Here is the class structure
[Verb("open", HelpText = "Open an application")]
public class OpenOptions
{
[Option("id", "appId", Required = false, HelpText = "Application Id")]
public int ApplicationId{ get; set; }
[Option("name", "appName", Required = false, HelpText = "Application Name")]
public string ApplicationName{ get; set; }
[Option("uId", "userId", Required = true, HelpText = "User Id")]
public Guid UserId{ get; set; }
}

There is no out-of-the-box solution. Normally HttpUtility class (ref Get URL parameters from a string in .NET) can do the trick.
Here is the first approach:
var url = "https://localhost:9000/Open?appId=123&appName=paint&uId=511a3434-37e0-4600-ab09-65728ac4d8fe";
Uri uri = new Uri(url);
var #params = HttpUtility.ParseQueryString(uri.Query);
string? appId = #params.Get("appId");
Console.WriteLine(appId);
Will return 123, and so on with your other parameters.
The returned value will be a string type. You can eventually use Guid.TryParse to parse your Guid object and int.TryParse for an int value.

CommandLineParser is not made for parsing Uri's. But using the Uri class and Linq, this is quite easy:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var (verb, query) = ParseUri("https://localhost:9000/Open/appId=123&appName=paint&uId=511a3434-37e0-4600-ab09-65728ac4d8fe");
var appId = query["appId"];
var appName = query["appName"];
var uId = query["uId"];
Console.WriteLine($"verb='{verb}'");
Console.WriteLine($"appId='{appId}', appName='{appName}', uId='{uId}'");
}
static (string verb, Dictionary<string, string> args) ParseUri(string strUri)
{
var uri = new Uri(strUri);
// get the verb
var verb = uri.Segments[1].TrimEnd('/');
// get the query part as dictionary
var args = uri.Segments[2].Split('&')
.Select(s => s.Split('=')).ToDictionary(d => d[0], d => d[1]);
return (verb, args);
}
}
First parsing happens by instantiating an Uri allowing to use the Segments property. Then split the query by using & and finally create a dictionary by using = to split the key/value pair.
Because query is a Dictionary, you can simply access individual query parameters like:
var appId = query["appId"];
var appName = query["appName"];
var uId = query["uId"];
Console.WriteLine($"verb='{verb}'");
Console.WriteLine($"appId='{appId}', appName='{appName}', uId='{uId}'");
which prints:
verb='Open'
appId='123', appName='paint', uId='511a3434-37e0-4600-ab09-65728ac4d8fe'
Note: In LinqPad, you can use query.Dump(verb);
to visualize the result:

var link = "https://localhost:9000/Open?appId=123&appName=paint&uId=511a3434-37e0-4600-ab09-65728ac4d8fe";
var uri = new Uri(link);
var command = uri.LocalPath.TrimStart('/').ToLower();
var query = HttpUtility.ParseQueryString(uri.Query);
var sb = new StringBuilder($"{command} ");
foreach(string key in query)
{
sb.Append($"-{key} {query.Get(key)} ");
}
var commandWithArgs = sb.ToString();

Related

Azure Search SDK fails partial search when using special characters

I have a below code which should return all the names starting with T&S from azure index
for example the results should be like below
T&S
T&S Limited
T&S Corporation
The search text we see in the code is the UrlEncoded version of "T&S*"
Search Code Block
var response = await _searchClient.Documents.SearchAsync<customDto>("%22T%26S%22*",
new SearchParameters
{
SearchFields = new List<string> { "Name" },
SearchMode = SearchMode.All
});
Custom DTO
public class CustomDto{
public CustomDto(int id,string name)
{
Id=Convert.ToString(id),
Name=name
}
[IsSearchable, IsFilterable]
[System.ComponentModel.DataAnnotations.Key]
public string Id { get; }
[IsSearchable, IsFilterable, IsSortable]
public string Name {get;}
}
Now,
If i put the similar search text on the azure search query window
i get results as expected %22T%26S%22*&searchMode=all&searchFields=Name
But for some reason the code returns empty result. I dont get what am i doing wrong here.
Please assist.
Thank you
Can you try with the following code. This uses Microsoft.Azure.Search SDK (version 10.1.0).
var searchCredentials = new SearchCredentials("<api-key (admin or query>");
var indexClient = new SearchIndexClient("<search-service-name>", "<index-name>", searchCredentials);
var results = indexClient.Documents.Search("\"T\\&S\"*",
new SearchParameters
{
SearchFields = new List<string> { "Name" },
SearchMode = SearchMode.All
});
SDK actually makes a POST request so you don't really have to URL encode the search string (you would need to do that when you issue a GET request). What you need to do is escape & character by prefixing it with a \ and that's what I did. Please see Escaping Special Characters here: https://learn.microsoft.com/en-us/azure/search/query-lucene-syntax#bkmk_syntax for more information.

Custom fields with spaces in Workfront issues

Please, can you help me create/update items from custom fields that have space within their name?
We have a project with a custom field Contact phone. This field can be used correctly from the browser. https://github.com/Workfront/workfront-api-examples-csharp didn't help. I was able to add the data within the details of the issue. I would like to add it within the specific custom field (create/update).
var client = new AtTaskRestClient(_url); // from the example
...
var description = $"Contact phone: {item.ContactPhone}";
client.Create(ObjCode.ISSUE, new { name = item.Name,
description = description,
projectID = _projectID });
client.Create has an object as final parameter. We use an anonymous type that can't contain "DE:Contact phone" = item.ContactPhone within the constructor. How can we write this field?
Reading DE:Contact phone works correctly if we insert the value from the browser:
JToken issues = client.Search(ObjCode.ISSUE, new { projectID = _projectID });
foreach (var issue in issues["data"].Children()) {
var name = issue.Value<string>("name"); // correct
var id = issue.Value<string>("ID"); // correct
var fields = client.Get(ObjCode.ISSUE, id, new[] { "description", "DE:Contact phone"}); // correct
https://github.com/Workfront/workfront-api-examples-csharp/blob/master/AtTaskRestExample/AtTaskRestClient.cs
public JToken Create(ObjCode objcode, object parameters) {
VerifySignedIn();
string[] p = parameterObjectToStringArray(parameters, "sessionID=" + SessionID);
JToken json = client.DoPost(string.Format("/{0}", objcode), p);
return json;
}
I wrote a new function CreateEx, that receives a string array
public JToken Create(ObjCode objcode, string[] parameters) {
VerifySignedIn();
JToken json = client.DoPost(string.Format("/{0}", objcode), parameters);
return json;
}
It is accessed as follows:
var client = new AtTaskRestClient(_url); // from the example
...
string[] parameteres =
{
$"name={issueName}",
$"description={description}",
$"projectID={_projectID}",
$"sessionID={client.SessionID}",
$"DE:Contact phone={contactPhone}"
};
client.CreateEx(ObjCode.ISSUE, parameteres);

Easier way to extract ID from a string? [duplicate]

I would like to parse a string such as p1=6&p2=7&p3=8 into a NameValueCollection.
What is the most elegant way of doing this when you don't have access to the Page.Request object?
There's a built-in .NET utility for this: HttpUtility.ParseQueryString
// C#
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
' VB.NET
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)
You may need to replace querystring with new Uri(fullUrl).Query.
HttpUtility.ParseQueryString will work as long as you are in a web app or don't mind including a dependency on System.Web. Another way to do this is:
NameValueCollection queryParameters = new NameValueCollection();
string[] querySegments = queryString.Split('&');
foreach(string segment in querySegments)
{
string[] parts = segment.Split('=');
if (parts.Length > 0)
{
string key = parts[0].Trim(new char[] { '?', ' ' });
string val = parts[1].Trim();
queryParameters.Add(key, val);
}
}
A lot of the answers are providing custom examples because of the accepted answer's dependency on System.Web. From the Microsoft.AspNet.WebApi.Client NuGet package there is a UriExtensions.ParseQueryString, method that can also be used:
var uri = new Uri("https://stackoverflow.com/a/22167748?p1=6&p2=7&p3=8");
NameValueCollection query = uri.ParseQueryString();
So if you want to avoid the System.Web dependency and don't want to roll your own, this is a good option.
I wanted to remove the dependency on System.Web so that I could parse the query string of a ClickOnce deployment, while having the prerequisites limited to the "Client-only Framework Subset".
I liked rp's answer. I added some additional logic.
public static NameValueCollection ParseQueryString(string s)
{
NameValueCollection nvc = new NameValueCollection();
// remove anything other than query string from url
if(s.Contains("?"))
{
s = s.Substring(s.IndexOf('?') + 1);
}
foreach (string vp in Regex.Split(s, "&"))
{
string[] singlePair = Regex.Split(vp, "=");
if (singlePair.Length == 2)
{
nvc.Add(singlePair[0], singlePair[1]);
}
else
{
// only one key with no value specified in query string
nvc.Add(singlePair[0], string.Empty);
}
}
return nvc;
}
To do this without System.Web, without writing it yourself, and without additional NuGet packages:
Add a reference to System.Net.Http.Formatting
Add using System.Net.Http;
Use this code:
new Uri(uri).ParseQueryString()
https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx
I needed a function that is a little more versatile than what was provided already when working with OLSC queries.
Values may contain multiple equal signs
Decode encoded characters in both name and value
Capable of running on Client Framework
Capable of running on Mobile Framework.
Here is my solution:
Public Shared Function ParseQueryString(ByVal uri As Uri) As System.Collections.Specialized.NameValueCollection
Dim result = New System.Collections.Specialized.NameValueCollection(4)
Dim query = uri.Query
If Not String.IsNullOrEmpty(query) Then
Dim pairs = query.Substring(1).Split("&"c)
For Each pair In pairs
Dim parts = pair.Split({"="c}, 2)
Dim name = System.Uri.UnescapeDataString(parts(0))
Dim value = If(parts.Length = 1, String.Empty,
System.Uri.UnescapeDataString(parts(1)))
result.Add(name, value)
Next
End If
Return result
End Function
It may not be a bad idea to tack <Extension()> on that too to add the capability to Uri itself.
If you don't want the System.Web dependency, just paste this source code from HttpUtility class.
I just whipped this together from the source code of Mono. It contains the HttpUtility and all it's dependencies (like IHtmlString, Helpers, HttpEncoder, HttpQSCollection).
Then use HttpUtility.ParseQueryString.
https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c
If you want to avoid the dependency on System.Web that is required to use HttpUtility.ParseQueryString, you could use the Uri extension method ParseQueryString found in System.Net.Http.
Make sure to add a reference (if you haven't already) to System.Net.Http in your project.
Note that you have to convert the response body to a valid Uri so that ParseQueryString (in System.Net.Http)works.
string body = "value1=randomvalue1&value2=randomValue2";
// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();
I just realized that Web API Client has a ParseQueryString extension method that works on a Uri and returns a HttpValueCollection:
var parameters = uri.ParseQueryString();
string foo = parameters["foo"];
private void button1_Click( object sender, EventArgs e )
{
string s = #"p1=6&p2=7&p3=8";
NameValueCollection nvc = new NameValueCollection();
foreach ( string vp in Regex.Split( s, "&" ) )
{
string[] singlePair = Regex.Split( vp, "=" );
if ( singlePair.Length == 2 )
{
nvc.Add( singlePair[ 0 ], singlePair[ 1 ] );
}
}
}
Just access Request.QueryString. AllKeys mentioned as another answer just gets you an array of keys.
HttpUtility.ParseQueryString(Request.Url.Query) return is HttpValueCollection (internal class). It inherits from NameValueCollection.
var qs = HttpUtility.ParseQueryString(Request.Url.Query);
qs.Remove("foo");
string url = "~/Default.aspx";
if (qs.Count > 0)
url = url + "?" + qs.ToString();
Response.Redirect(url);
Since everyone seems to be pasting his solution.. here's mine :-)
I needed this from within a class library without System.Web to fetch id parameters from stored hyperlinks.
Thought I'd share because I find this solution faster and better looking.
public static class Statics
public static Dictionary<string, string> QueryParse(string url)
{
Dictionary<string, string> qDict = new Dictionary<string, string>();
foreach (string qPair in url.Substring(url.IndexOf('?') + 1).Split('&'))
{
string[] qVal = qPair.Split('=');
qDict.Add(qVal[0], Uri.UnescapeDataString(qVal[1]));
}
return qDict;
}
public static string QueryGet(string url, string param)
{
var qDict = QueryParse(url);
return qDict[param];
}
}
Usage:
Statics.QueryGet(url, "id")
Hit up Request.QueryString.Keys for a NameValueCollection of all query string parameters.
To get all Querystring values try this:
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)
Dim sb As New StringBuilder("<br />")
For Each s As String In qscoll.AllKeys
Response.Write(s & " - " & qscoll(s) & "<br />")
Next s
var q = Request.QueryString;
NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());
I translate to C# version of josh-brown in VB
private System.Collections.Specialized.NameValueCollection ParseQueryString(Uri uri)
{
var result = new System.Collections.Specialized.NameValueCollection(4);
var query = uri.Query;
if (!String.IsNullOrEmpty(query))
{
var pairs = query.Substring(1).Split("&".ToCharArray());
foreach (var pair in pairs)
{
var parts = pair.Split("=".ToCharArray(), 2);
var name = System.Uri.UnescapeDataString(parts[0]);
var value = (parts.Length == 1) ? String.Empty : System.Uri.UnescapeDataString(parts[1]);
result.Add(name, value);
}
}
return result;
}
let search = window.location.search;
console.log(search);
let qString = search.substring(1);
while(qString.indexOf("+") !== -1)
qString = qString.replace("+", "");
let qArray = qString.split("&");
let values = [];
for(let i = 0; i < qArray.length; i++){
let pos = qArray[i].search("=");
let keyVal = qArray[i].substring(0, pos);
let dataVal = qArray[i].substring(pos + 1);
dataVal = decodeURIComponent(dataVal);
values[keyVal] = dataVal;
}
This is my code, I think it's very useful:
public String GetQueryString(string ItemToRemoveOrInsert = null, string InsertValue = null )
{
System.Collections.Specialized.NameValueCollection filtered = new System.Collections.Specialized.NameValueCollection(Request.QueryString);
if (ItemToRemoveOrInsert != null)
{
filtered.Remove(ItemToRemoveOrInsert);
if (!string.IsNullOrWhiteSpace(InsertValue))
{
filtered.Add(ItemToRemoveOrInsert, InsertValue);
}
}
string StrQr = string.Join("&", filtered.AllKeys.Select(key => key + "=" + filtered[key]).ToArray());
if (!string.IsNullOrWhiteSpace(StrQr)){
StrQr="?" + StrQr;
}
return StrQr;
}

How to create JSON from strings without creating a custom class using JSON.Net library

I have this method in which I'm trying to create JSON string:
//my current file
using Newtonsoft.Json;
string key1 = "FirstKey";
string key2 = "SecondKey";
string key3 = "ThirdKey";
private string CreateJson(string val1, string val2, string val3,string val4, string val5, string val6)
{
//process the six arguments and three key-related member variables to create a JSON array
//don't want to use JsonConvert.SerializeObject the way I'm doing below as it requires creating a class
var configs = new List<CustomClass>
{ new CustomClass{ FirstKey = val1,SecondKey= val2,ThirdKey= val3}
, new CustomClass{ FirstKey= val4,SecondKey= val5,ThirdKey = val6}
};
var jsonData = JsonConvert.SerializeObject(configs);
return jsonData;
}
//A class in another file
public class CustomClass
{
public string FirstKey { get; set; }
public string SecondKey{ get; set; }
public string ThirdKey{ get; set; }
}
I'm trying to create the JSON array using JSON.Net. The expected output is as below:
[{"FirstKey":val1,"SecondKey":val2,"ThirdKey":val3}
, {"FirstKey":val4,"SecondKey":val5,"ThirdKey":val6}]
Here val1 to val6 values should get replaced by the argument values at run-time.
Initially, since there were just three types of string key-value pairs, so I thought it would be pretty straightforward to create a JSON string simply by using string literals and appending then one after the other in JSON format. But soon I stumbled upon the world of escape characters which can deform a JSON string e.g. \r.
I had been using JSON.Net library in the past simply to serialize and deserialize objects using JSONConvert class and I never cared and was completely unaware about this handling of escape characters by JSON.Net library does behind the scene for us to keep the JSON string valid.
Anyways, coming back to my problem. I was able to solve my problem by creating a custom class having three properties FirstKey, SecondKey, and ThirdKey. Then, create an object of the class, then assign the values in arguments val1 and val2 to then and then use JsonConvert.SerializeObject API.
I want a very simply way of creating JSON string using JSON.Net NuGet package without involving custom classes. Creating a class CustomClass altogether feels like an overhead here. I'm looking for something of sort of like StringBuilder.Append API if it is available in the JSON library I'm using. I'm not sure if I'm missing any of the APIs in JSON.Net.
As mentioned in the comments, you could just as easily have created it using anonymous objects.
private string CreateJson(string val1, string val2, string val3, string val4, string val5, string val6) {
var configs = new[]
{
new { FirstKey = val1, SecondKey = val2, ThirdKey = val3},
new { FirstKey = val4, SecondKey = val5, ThirdKey = val6}
};
var jsonData = JsonConvert.SerializeObject(configs);
return jsonData;
}
Here's an alternate way of doing it.
My use case is I need to read a CSV file, and create JSON output based on the CSV headers.
I do not know what the key names will be. Every CSV file could have different headers.
Rick Strahl shows us how to do it # https://weblog.west-wind.com/posts/2012/aug/30/using-jsonnet-for-dynamic-json-parsing
And here's a simple implementation using JObject and JArray
Create a dotnet new console project and add the nuget package for Newtonsoft
dotnet new console -n "Json.TypeLess"
dotnet add package Newtonsoft.Json --version 13.0.1
Program.cs to have :
using Newtonsoft.Json.Linq;
namespace Json.TypeLess
{
public class Program
{
public static void Main(string[] args)
{
var records = new JArray();
records.Add(CreateRecord("Johhny", "Singing"));
records.Add(CreateRecord("Arjun", "Eating"));
records.Add(CreateRecord("Sahil", "Reading"));
records.Add(CreateRecord("Karthik", "Wuxia"));
Console.WriteLine(records.ToString());
}
static JObject CreateRecord(string name, string likes)
{
var r = new JObject();
r.Add("Name", name);
r.Add("Likes", likes);
return r;
}
}
}
Output
[
{
"Name": "Johhny",
"Likes": "Singing"
},
{
"Name": "Arjun",
"Likes": "Eating"
},
{
"Name": "Sahil",
"Likes": "Reading"
},
{
"Name": "Karthik",
"Likes": "Wuxia"
}
]
Without using NewtonSoft Json
The above can also be achieved using System.Text.Json.Nodes namespace from .net's native classes ( I tested using .net 6.0 )
Intead of JObject use JsonObject
and instead of JArray use JsonArray
and to get json output, use ToJsonString() method on the object
Getting few clues from [#code4life][1]'s comment in accepted answer, I found out that it is achievable via JArray object as well found under Newtonsoft.Json.Linq namespace.
using Newtonsoft.Json.Linq;
private string CreateJson(string val1, string val2, string val3, string val4, string val5, string val6)
{
var configs = new[]
{
new { FirstKey = val1, SecondKey = val2, ThirdKey = val3},
new { FirstKey = val4, SecondKey = val5, ThirdKey = val6}
};
return JArray.FromObject(configs).ToString();
}
Note: Anonymous types which are being created through new { FirstKey = val1, SecondKey = val2, ThirdKey = val3} syntax can contain any .NET data type and not just strings which I've asked in my original post e.g.new { FirstKey = "AnyString", SecondKey = true, ThirdKey = DateTime.Now}
[1]: https://stackoverflow.com/users/215741/code4life
There's JsonWriter, which is not much more than StringBuilder - you do not get much constraints and can possibly end up with incorrect document
Some time ago I wanted to create simple documents WITHOUT the overhead of serialization, but with the guarantee they will be correct.
The pattern I went with is:
var doc = JSONElement.JSONDocument.newDoc(true);
using (var root = doc.addObject())
{
root.addString("firstName", "John");
root.addString("lastName", "Smith");
root.addBoolean("isAlive", true);
root.addNumber("age", 27);
using (var addres = root.addObject("address"))
{
addres.addString("streetAddress", "21 2nd Street");
addres.addString("city", "New York");
addres.addString("state", "NY");
addres.addString("postalCode", "10021-3100");
}
using (var phoneNumbers = root.addArray("phoneNumbers"))
{
using (var phone = phoneNumbers.addObject())
{
phone.addString("type", "home");
phone.addString("number", "212 555-1234");
}
//[....]
}
}
string output = doc.getOutput();
}
The module (< 300lines) is available here: https://github.com/AXImproveLtd/jsonDocCreate

C# Array Conversion

Any help here as I'm a C# noob. The following code works fine and returns 1 string ViewState2. I'd like it to return an array of ViewState2 and EventValidation2 so I can manipulate it later on. How would I convert the code below to return an array?
public string get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string ViewState2 = ViewState.Attributes[3].Value;
string EventValidation2 = EventValidation.Attributes[3].Value;
//Display the values
//System.Console.WriteLine(ViewState.Attributes[3].Value);
//System.Console.WriteLine(EventValidation.Attributes[3].Value);
//System.Console.ReadKey();
return ViewState2;
}
Don't use an array, but a class. Doing this, you don't have to remember what each element means.
public class Status
{
public string ViewState {get; set;}
public string EventValidation {get; set;}
}
using System;
using HtmlAgilityPack;
[...]
public Status GetStatus(string localFileName)
{
var dtsDoc = new HtmlDocument();
dtsDoc.Load(localFileName);
//Pull the values
var viewStateNode = dtsDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var eventValidationNode = dtsDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string viewState = viewStateNode.Attributes[3].Value;
string eventValidation = eventValidationNode.Attributes[3].Value;
//Display the values
//Console.WriteLine(viewState);
//Console.WriteLine(eventValidation);
//Console.ReadKey();
return new Status
{
ViewState = viewState,
EventValidation = eventValidation
}
}
Also, you should read up on coding guidelines and naming conventions in the C# language, also the using statement might be interesting. I have corrected some "mistakes", but probably didn't catch all. Also, I have renamed a couple of variables, to make their content clearer. You also might want to look into using the var keyword only in a loop, while using LINQ (or anomynous types in general) or with really long class names. Written out type names can increase readability quite a lot.
If you really want an array with ViewState2 and EventValidation2 in it, you can make the following changes:
// Notice: return value of string[] instead of string
public string[] get_status(string local_frame);
And:
// Notice: returning an array
return new string[] { ViewState2, EventValidation2 };
That said, this is really the "quick and dirty" approach, and is not really appropriate if you're going to want this code to be maintainable (when's the last time you read documentation on a function that "returns an array of length 2, with a string representing X as the first element and another string representing Y as the second"?).
Femaref's right; the correct thing to do would be to encapsulate the information you want returned in its own type.
Assuming you answer yes to this question (although I'd recommend a different approach, see below) this will do what you're asking:
public String[] get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string ViewState2 = ViewState.Attributes[3].Value;
string EventValidation2 = EventValidation.Attributes[3].Value;
String[] retValues = new String[2];
retValues[0] = ViewState2;
retValues[1] = EventValidation2;
return retValues;
//Display the values
//System.Console.WriteLine(ViewState.Attributes[3].Value);
//System.Console.WriteLine(EventValidation.Attributes[3].Value);
//System.Console.ReadKey();
return ViewState2;
}
That said, I would follow the approach afte the line.
I'd write a class that has the data members you want:
public class DataClass
{
public string ViewState { get; set; }
public string EventValidation { get; set; }
}
Then I'd modify the method to return an instance of your data class.
public DataClass get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
var dc = new DataClass();
dc.ViewState = ViewState.Attributes[3].Value;
dc.EventValidation = EventValidation.Attributes[3].Value;
return dc;
}
string[] array = new string[2];
array[0] = ViewState2;
array[1] = EventValidation2;
return array;
But it seems to trivial as answer. Please Does it solve your problem? If no, can you specify better the question please?

Categories