How to reliably build a URL in C# using the parts? - c#

I keep feeling like I'm reinventing the wheel, so I thought I'd ask the crowd here. Imagine I have a code snippet like this:
string protocol = "http"; // Pretend this value is retrieved from a config file
string host = "www.google.com"; // Pretend this value is retrieved from a config file
string path = "plans/worlddomination.html"; // Pretend this value is retrieved from a config file
I want to build the url "http://www.google.com/plans/worlddomination.html". I keep doing this by writing cheesy code like this:
protocol = protocol.EndsWith("://") ? protocol : protocol + "://";
path = path.StartsWith("/") ? path : "/" + path;
string fullUrl = string.Format("{0}{1}{2}", protocol, host, path);
What I really want is some sort of API like:
UrlBuilder builder = new UrlBuilder();
builder.Protocol = protocol;
builder.Host = host;
builder.Path = path;
builder.QueryString = null;
string fullUrl = builder.ToString();
I gotta believe this exists in the .NET framework somewhere, but nowhere I've come across.
What's the best way to build foolproof (i.e. never malformed) urls?

Check out the UriBuilder class

UriBuilder is great for dealing with the bits at the front of the URL (like protocol), but offers nothing on the querystring side. Flurl [disclosure: I'm the author] attempts to fill that gap with some fluent goodness:
using Flurl;
var url = "http://www.some-api.com"
.AppendPathSegment("endpoint")
.SetQueryParams(new {
api_key = ConfigurationManager.AppSettings["SomeApiKey"],
max_results = 20,
q = "Don't worry, I'll get encoded!"
});
There's a new companion library that extends the fluent chain with HTTP client calls and includes some nifty testing features. The full package is available on NuGet:
PM> Install-Package Flurl.Http
or just the stand-alone URL builder:
PM> Install-Package Flurl

Related

C# - Uribuilder without parameter names

I've just started using .netcore.
I need to create a url, I've come across UriBuilder however I can only see example of using that with named paramters e.g.: localhost?value=abc&another=def, however I want to construct without parameter names, so:
localhost/abc/def/
Is this possible, I was thinking maybe something like the below:
var request = new HttpRequestMessage();
request.RequestUri = new Uri(_myUrl);
request.Method = HttpMethod.Get;
var uriBuilder = new UriBuilder(request.RequestUri);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query[0] = "abc"
Any help appreciated.
That's not how UriBuilder or URIs work. What you are trying to change/set is the path of the URI. That is done using the Path property, or using the relevant constructor of UriBuilder. Your example shows how to change/set the Query-String (key-value pairs, basically).
How you create the path is not the business of the UriBuilder class (see #Irdis comment about an option).
Basically, you can create your path manually using string manipulation of your choice, then assign it to the Path property, e.g.:
var b = new UriBuilder(...);
// Set other properties to your requirements
b.Path = "/the/path/ optional with spaces and other stuff/";
You can then use the UriBuilder.Uri property to get the full URI or use the UriBuilder.ToString() method to get the properly escaped URI. For the above example that would be something like:
http://localhost/the/path/%20optional%20with%20spaces%20and%20other%20stuff/

Looking for client side Json/WebAPI package to send HttpGet/HttpPost messages

BACKGROUND
currently I am in a side project where I am building a Xamarin based mobile App for easy movie and tv show searching and navigation based on user preferences (e.g. based on movie genre etc).
To do this the mobile app acts as a client to the https://www.themoviedb.org/documentation/api online movie database's Web API service.
PROBLEM
I am looking for an easy and well supported package to wrap API Uri paths and query parameters into a web api query. I have looked a bit on RestSharp .
I like the syntax very much with the pattern based query path:
var request = new RestRequest("resource/{id}");
request.AddParameter("name", "value");
request.AddUrlSegment("id", "123");
but I am not sure about the packages future. Also if there is an alternative from MS, I would take that.
So have also looked Web-API tailored at MS alternatives but I am unsure what is recommended there. I only can find docs and examples for the server side (ASP.NET CORE MVC).
I need to be pointed to a well functioning .NET Standard 2.0 package from Microsoft or from a 3rd party to send Web API request from my Xamarin client.
Where am I
I have already written a lot of code based on pure HttPClient and AspNetcore.WebUtilituies for assembling a query string. But the gazillions of API path segments are getting out of my hand. I really need something to manage API path templates like RestSharp does
Code sample:
here I declare all of the path segments which I assemble manually ==> ugly AF
public static class WebApiPathConstants
{
public const string BASE_Address = "https://api.themoviedb.org";
public const string BASE_Path = "/3";
public const string CONFIG_Path = "/configuration";
public const string GENRE_LIST_Path = "/genre/movie/list";
...
lot of lines here
....
public const string PAGE_Key = "page";
public const string INCLUDE_Adult_Key = "include_adult";
public const string API_KEY_Key = "api_key";
public const string RECOMMENDATIONS_Path = "/recommendations";
public const string SIMILARS_Path = "/similar";
}
Here I assemble a query and kick of a task to get movie details based on the query from the server: The assembly of the Url path is my main problem. It looks too error prone.
public async Task<FetchMovieDetailsResult> FetchMovieDetails(int id, string language = null, int retryCount = 0, int delayMilliseconds = 1000)
{
string baseUrl = BASE_Address + BASE_Path + MOVIE_DETAILS_Path + "/" + id;
var query = new Dictionary<string, string>();
query.Add(API_KEY_Key, apiKeyValue);
if (!string.IsNullOrEmpty(language))
query.Add(LANGUAGE_Key, language);
string requestUri = QueryHelpers.AddQueryString(baseUrl, query);
FetchMovieDetailsResult result = await GetResponse<FetchMovieDetailsResult>(retryCount, delayMilliseconds, requestUri);
return result;
}
The result is a POCO class with the HttpStatusCode and (if successful ) a Json object. The client accesses the Json object only if the StatusCode == 2xx.
Prepared to be shot down in flames here, if this doesn't match your use-case, but it looks like the TheMovieDb site itself has a list of client libraries. It's available here: https://www.themoviedb.org/documentation/api/wrappers-libraries. They're obviously a layer higher than you're asking for here, in that they completely wrap the API, such that you need not even know what you're calling or how you're calling it, but in the interests of getting the job done, they seem like they'd do the trick.

Access Moodle API from .Net Console Application

For one of my projects I need to manage some of the attributes of our Moodle, including (but probably not limited to) Creating/Updating users and managing enrolments.
I need to create this interface in a .Net (4.0+) Console application, so information can be processed from other systems.
I have checked NuGet for packages for Moodle but I cant find anything.
Can you advise on how I could achieve this interface?
Thanks in advance.
I don't think there is a wrapper available for this. You will need to enable moodle webservices:
https://docs.moodle.org/dev/Web_services
And create your own. I am using RestSharp for this:
https://www.nuget.org/packages/RestSharp
This code will work for accessing course information
string result = "";
string methodName = "GetCourse";
string apiName = "core_course_get_courses";
string apiCall = moodleUrl + "?wstoken=" + token + "&wsfunction=" + apiName + "&moodlewsrestformat=json";
try
{
using (WebClient client = new WebClient())
{
client.BaseAddress = apiCall;
client.Headers[HttpRequestHeader.Accept] = "application/json";
result = client.DownloadString(apiCall);

Can HTTP requests be unintentionally cached?

The following HTTP fetch should return the string 262. For some of my users (but not all, or even most) it seems to be returning an older value 261.
string latestVersion = new System.Net.WebClient().DownloadString(
"http://www.pixelchampions.com/latest.txt");
I don't really know why. IIS7 is using mostly default settings. Do some routers/ISPs cache the results of non-query HTTP requests?
You can try this (or one of the other RequestCacheLevel settings):
WebClient MyClient = new System.Net.WebClient() ;
MyClient.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
string latestVersion = MyClient.DownloadString(
"http://www.pixelchampions.com/latest.txt");

How would you detect the current browser in an Api Controller?

I'm trying to detect the current web browser within one of my Api Controllers in my program using MVC4. Everywhere I look people say to use Request.Browser, however I can't get that to work. Any suggestions or is there something I'm overlooking?
You can use the HttpBrowserCapabilities in System.Web like this
var userAgent = HttpContext.Current.Request.UserAgent;
var userBrowser = new HttpBrowserCapabilities { Capabilities = new Hashtable { { string.Empty, userAgent } } };
var factory = new BrowserCapabilitiesFactory();
factory.ConfigureBrowserCapabilities(new NameValueCollection(), userBrowser);
//Set User browser Properties
BrowserBrand = userBrowser.Browser;
BrowserVersion = userBrowser.Version;
This relies on browscap.ini in Windows/System32/inetsrv/ or Windows/SysWOW64/inetsrv for definitions.
This article may also help - http://stephenwalther.com/archive/2010/03/05/use-asp-net-4-browser-definitions-with-asp-net-3-5
You could do something like following too from within the Web API's action:
System.Net.Http.HttpRequestMessage currentRequest = this.Request;
System.Net.Http.Headers.HttpHeaderValueCollection<System.Net.Http.Headers.ProductInfoHeaderValue> userAgentHeader = currentRequest.Headers.UserAgent;

Categories

Resources