C# WebApi sending a request from Global.asax resulting in a 404 - c#

I have a situation where I'm attempting to keep my web api application alive by sending a request to an MVC controller in the Api. I am getting the url in the Application_BeginRequest method in the Global.asax, then basically disassembling the URL and constructing it to hit a known controller method (route). When I get the url that it constructs and paste it in a browser the url works fine and returns the expected result. However when I user the same url in the application I get a 404 error.
Global.asax method that gets the URL from the first request:
void Application_BeginRequest(Object source, EventArgs e)
{
if (!initialized)
{
var rawurl = HttpContext.Current.Request.Url.AbsoluteUri;
capturedRequest = HttpContext.Current.Request;
if (!String.IsNullOrEmpty(rawurl))
{
if(!rawurl.ToLower().Contains("api"))
{
return;
}
lock (locked)
{
var urlparts = rawurl.Split('/');
if (urlparts.Length > 0)
{
siteUrl = "http://";
for (int i = 1; i < urlparts.Length - 1; i++)
{
if (!String.IsNullOrEmpty(urlparts[i]))
{
siteUrl += urlparts[i] + "/";
}
}
if (urlparts[urlparts.Length - 1].ToLower().Contains("api"))
{
siteUrl += urlparts[urlparts.Length - 1];
}
if(siteUrl[siteUrl.Length -1] != '/')
{
siteUrl += "/";
}
siteUrl += "Labels/GetAllDeploymentLabels";
initialized = true;
}
}
}
}
}
This gets the correct URL. I have a timer which every five minutes calls this method, also in the Global.asax method: (it returns a 404 error in the message.
private async void MakeKeepAliveRequest()
{
Repository repository = new Repository();
if (!String.IsNullOrEmpty(WebApiApplication.siteUrl))
{
try
{
HttpClient client = new HttpClient();
HttpResponseMessage message = await client.GetAsync(new Uri(WebApiApplication.siteUrl));
repository.WriteToApplicationLog("Keep Alive", null, Environment.MachineName + " : " + WebApiApplication.siteUrl + ": Global ASAX Keep Alive REQUEST SUCCEEDED: " + message + DateTime.Now, Core.ApplicationMessageType.Message);
}
catch (Exception ex)
{
repository.WriteToApplicationLog("Keep Alive", null, Environment.MachineName + ": Global ASAX Keep Alive REQUEST FAILED: " + ex.Message + " ::: " + DateTime.Now, Core.ApplicationMessageType.Message);
}
}
}
What am I missing, why can't it find the url from code, but works fine from the browser?

Related

Windows service calling WebGet method returns 400 error

I have a service that runs a c# method to sync a database with active directory at a specified interval. This code has worked in a test environment and now putting it on a different server it is returning the following message:
The server encountered an error processing the request. Please see the
service help page for constructing valid requests to the service.
The help page looks like this:
But the "SyncActiveDirectory" URI is giving me this error:
This is a new server. Maybe i am missing something that needs to be installed or a setting in IIS? Any help would be much appreciated.
EDIT:
Here is the method that called the webget:
private void SyncActiveDirectoryServiceCall()
{
WriteIntoLogFile("Start _schedulerService.SyncActiveDirectoryServiceCall()");
try
{
var reader = new AppSettingsReader();
var serviceurl = reader.GetValue("ServiceUrl", typeof(string));
var client = new RestSharp.RestClient(serviceurl.ToString());
var request = new RestSharp.RestRequest("SyncActiveDirectory", RestSharp.Method.GET);
var response = client.Execute(request);
WriteIntoLogFile(response.Content);
}
catch (WebException ex)
{
using (WebResponse response = ex.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)response;
WriteIntoLogFile("Error code: " + httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
string text = reader.ReadToEnd();
WriteIntoLogFile("STREAMED: " + text);
}
}
WriteIntoLogFile("TRY-CATCH: " + ex.ToString());
}
WriteIntoLogFile("End _schedulerService.SyncActiveDirectoryServiceCall()");
}
And here is the method being called:
namespace SyncActiveDirectory
{
public class SyncLocalWithLDAP : ISyncLocalWithLDAP
{
private List<GenericUser> users { get; set; }
private List<GenericUser> roles { get; set; }
[WebGet(UriTemplate = "SyncActiveDirectory")]
public void SyncActiveDirectory()
{
string constr = GetConnectionStringValue("ProteusMMXCustomerDB");
string usr = GetAppsettingValue("ldap_login_username");
string pss = GetAppsettingValue("ldap_login_password");
string filePath = string.Empty;
ActiveDirectoryWrapper wrapper = new ActiveDirectoryWrapper();
if (!Directory.Exists(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog"))
{
Directory.CreateDirectory(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog");
}
if (!File.Exists(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + "/" + "SyncLog.txt"))
{
File.Create(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + "/" + "SyncLog.txt").Dispose();
}
filePath = WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + #"\" + "SyncLog.txt";
using (StreamWriter w = File.AppendText(filePath))
{
Log("Constr - " + constr + " , u - " + usr + " p - " + pss, w);
try
{
Log("Start sync outer", w);
SyncLocalWithLDAP_Users_Roles(constr, usr, pss, w);
Log("End sync outer", w);
}
catch (Exception ex)
{
Log("Error: " + ex.Message, w);
}
}
}
EDIT:
Pic of htm file added to that directory.
EDIT:
If this helps here is Chrome Developer Tools headers:

DownloadFile works, DownloadFileAsync gets 0 bytes file

I'm trying to download git from this url
https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe
I did it using DownloadFile, it worked OK.
Now I try to do it with Async method, but it downloads 0 byte file. Here's the code:
public void downloadFile(string urlAddress, string location)
{
using (var downloadClient = new WebClient())
{
downloadClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(Completed);
downloadClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
Uri URL = urlAddress.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(urlAddress) : new Uri("http://" + urlAddress);
_downloadStopWatch.Start();
try
{
downloadClient.DownloadFileAsync(URL, location);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
_downloadStopWatch.Stop();
while (downloadClient.IsBusy) { }
}
}
where:
private string _location = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\test.exe";
And urlAddress is typed into textbox and passed textbox.text
I check the Completed handler and it says completed.
Why am I getting 0 byte file?
The completed methods parameter AsyncCompletedEventArgs returns an error The remote name could not be resolved: 'https'.
In that case you should fall back to http
Depending on your target framework you could also use await downloadClient.DownloadFileTaskAsync(urlAddress, location);

Read a Cookie in a web service

I am trying to read a cookie sent through the client side in c# using a web service. I have got this code so far but my web service does not like request. Is there a better way to read a cookie through a web service. Just want to do it the best practice way.
int loop1, loop2;
HttpCookieCollection MyCookieColl;
HttpCookie MyCookie;
MyCookieColl = Request.Cookies;
// Capture all cookie names into a string array.
String[] arr1 = MyCookieColl.AllKeys;
// Grab individual cookie objects by cookie name.
for (loop1 = 0; loop1 < arr1.Length; loop1++)
{
MyCookie = MyCookieColl[arr1[loop1]];
Response.Write("Cookie: " + MyCookie.Name + "<br>");
Response.Write ("Secure:" + MyCookie.Secure + "<br>");
//Grab all values for single cookie into an object array.
String[] arr2 = MyCookie.Values.AllKeys;
//Loop through cookie Value collection and print all values.
for (loop2 = 0; loop2 < arr2.Length; loop2++)
{
Response.Write("Value" + loop2 + ": " + Server.HtmlEncode(arr2[loop2]) + "<br>");
}
}
Use below code
public String get_Cookie(String cookieName)
{
HTTPRequest Request = System.Web.HttpContext.Current.Request;
if (Request.Cookies.Get(cookieName) != null)
{
return HttpUtility.UrlDecode(Request.Cookies.Get(cookieName).Value);
}
else
{
return String.Empty;
}
}
I don't know if I understand your question, but I do this way:
public String get_Cookie(String cookieName)
{
HTTPRequest Request = this.Context.Request;//Added to better understanding.
if (Request.Cookies.Get(cookieName) != null)
{
return HttpUtility.UrlDecode(Request.Cookies.Get(cookieName).Value);
}
else
{
return String.Empty;
}
}

How can I post my data onto the server?

I am developing wp8 app. My question is that, The app is getting an error when I click on the registration button and the following exception occurred and the code is not going below string post data
An exception of type System.UnauthorizedAccessException occurred in System.Windows.ni.dll but was not handled in user code
If there is a handler for this exception, the program may be safely continue
namespace docapp
{
public partial class registration : PhoneApplicationPage
{
public static string DeviceIDAsString;
public registration()
{
InitializeComponent();
//selction.Items.Add("india");
//selction.Items.Add("pakistan");
//selction.Items.Add("china");
//selction.Items.Add("USA");
String[] name = { "india", "china", "pakistan" };
String[] uname = { "Delhi", "Bijing", "Karachi" };
String[] university = { "AIIMS", "MDU", "PGI" };
String[] yeardate = { "2011", "2012", "2013" };
string[] question = { "what is your pet name", "what is your childhood name", "what is your mother name" };
this.country.ItemsSource = name;
this.city.ItemsSource = uname;
this.university.ItemsSource = university;
this.year.ItemsSource = yeardate;
this.question.ItemsSource = question;
}
private void Image_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
{
if (txtusername.Text == "")
{
MessageBox.Show("enter the name");
}
else if (txtid.Text == "")
{
MessageBox.Show("enter valid id");
}
else if (txtpassword.Password == "")
{
MessageBox.Show("enter the password");
}
else if (txtconfirm.Password == "")
{
MessageBox.Show("enter the same password again ");
}
else if (txtemail.Text == "")
{
MessageBox.Show("enter the valid email id ");
}
else if (txtmobileno.Text == "")
{
MessageBox.Show("enter the valid 10 digit mobile no ");
}
if (txtpassword.Password != txtconfirm.Password)
{
MessageBox.Show("password doesnot match please enter same password");
}
SendPost();
//getDeviceId();
}
//private static String getDeviceId()
//{
// //byte[] id = (byte[])Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId");
// //return BitConverter.ToString(id).Replace("-", string.Empty);
// // get the unique device id for the publisher per device
//}
void SendPost()
{
byte[] myDeviceID = (byte[])Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId");
DeviceIDAsString = Convert.ToBase64String(myDeviceID);
Uri url = new Uri(" http://www.mobileoid2.co/docbase/index.php?methodname=createuser");
// Create the web request object
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.Headers["username"] = txtusername.Text;
webRequest.Headers["userid"] = txtid.Text;
webRequest.Headers["password"] = txtpassword.Password;
webRequest.Headers["confirmpaswword"] = txtconfirm.Password;
webRequest.Headers["email"] = txtemail.Text;
webRequest.Headers["mobileno"] = txtmobileno.Text;
webRequest.Headers["country"] = country.SelectedItem.ToString();
webRequest.Headers["city"] = city.SelectedItem.ToString();
webRequest.Headers["university"] = university.SelectedItem.ToString();
webRequest.Headers["year"] = year.SelectedItem.ToString();
webRequest.Headers["question"] = question.SelectedItem.ToString();
webRequest.Headers["uniqueid"] = DeviceIDAsString;
webRequest.ContentType = "application/json;charset=utf-8";
//"text/json";//
// Start the request
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
}
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
string postData = "username" + txtusername.Text + ".userid" + txtid.Text + "." + ".password" + txtpassword.Password + "." + ".confirmpassword" + txtconfirm.Password + "." + ".email" + txtemail.Text + "." + ".mobileno" + txtmobileno.Text + "." + "." + ".country" + country.SelectedItem.ToString() + "." + "." + ".city" + city.SelectedItem.ToString() + "." + "." + ".university" + university.SelectedItem.ToString() + "." + "." + ".year" + year.SelectedItem.ToString() + "." + ".question" + question.SelectedItem.ToString() + "." + ".uniqueid" + DeviceIDAsString +".";
var input = JsonConvert.SerializeObject(postData);
byte[] byteArray = Encoding.UTF8.GetBytes(input);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var Response = streamReader.ReadToEnd();
//outputbox.Text = Response.ToString();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
// Error treatment
// ...
}
}
private void Image_Tap_2(object sender, System.Windows.Input.GestureEventArgs e)
{
NavigationService.Navigate(new Uri("/docapp;component/login.xaml", UriKind.RelativeOrAbsolute));
}
}
}
Not sure why, but this error is generally thrown when the access is not allowed. Maybe the credentials you are trying to use are not allowed!
The issue is that the OS is denying the request due to I/O error, where the credentials are required, or you either don't have permission to read/write there, or the server needs a username/password match to allow you. Something like that. Try catching it using
try {
// code here to try..
} catch (System.UnauthorizedAccessException e) {
// error e.Message
}
Here is a Remark from the MSDN blog post:
An UnauthorizedAccessException exception is typically thrown by a method that wraps a Windows API call. To find the reasons for the exception, examine the text of the exception object's Message property.
For More: http://msdn.microsoft.com/en-us/library/system.unauthorizedaccessexception(v=vs.110).aspx

ASP.net Caching

I have implemented asp.net caching. But I am getting weird results
Unlike most caching where you are trying to avoid the amount of hits to the DB. I am trying to avoid any hits to the DB by the user. This is b/c the amount of time the fist page takes to load. It is basically a dashboard with a lot of charts and long running queries
I tried several techniques
1) Have the cache time very long and have a schedule process expire and get new cache.
2) and on RemoveCallback
In the second option I have all the cache go through a static class I created. The purpose is as it expires to refresh the data. Here is what I am calling.
Cache.Insert(dbCacheString, dtNetwork, null, DateTime.Now.AddHours(2),
System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High,
new CacheItemRemovedCallback(CacheManager.CacheRemovedCallback));
public static class CacheManager
{
private static Hashtable times = new Hashtable();
private static bool isRefreshingCache = false;
public static void CacheRemovedCallback(String key, object value,
CacheItemRemovedReason removedReason)
{
RefreshCache(key);
}
public static void StartCache()
{
string lcUrl = "http://localhost/ratingspage/";
// *** Establish the request
try
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("xxx", "xxx",
"xxx");
byte[] myDataBuffer = client.DownloadData(lcUrl);
}
catch (Exception ex)
{
ErrHandler.WriteError(ex.Message + "\n" +
ex.StackTrace.ToString());
LogUtil.LogDebugMessages(ex.Message + ":" +
ex.StackTrace.ToString());
}
}
public static void RefreshCache(string key)
{
string controlname = "";
if ( key.ToLower().StartsWith("control:") )
{
string[] tmp = key.Split(':');
if (tmp.Length > 1)
controlname = tmp[1];
else
return;
}
else
return;
string lcUrl = "http://localhost/ratingspage/Admin/" + "
"LoadControl.aspx?CachingSpider=true&Control=" + controlname;
string lcHtml = isRefreshingCache.ToString();
// *** Establish the request
if (!isRefreshingCache)
{
isRefreshingCache = true;
lcHtml = isRefreshingCache.ToString();
try
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("xxx",
"xxx", "xxx");
byte[] myDataBuffer = client.DownloadData(lcUrl);
lcHtml = Encoding.ASCII.GetString(myDataBuffer);
}
catch (Exception ex)
{
lcHtml = ex.Message;
isRefreshingCache = false;
ErrHandler.WriteError(ex.Message + "\n" +
ex.StackTrace.ToString());
LogUtil.LogDebugMessages(ex.Message + ":" +
ex.StackTrace.ToString());
}
isRefreshingCache = false;
}
MailMessage mail = new MailMessage(
new MailAddress("jgiblin#univision.net"),
new MailAddress("jgiblin#univision.net"));
mail.Subject = "Cache Expire: " + key;
mail.Body = string.Format("The Key {0} has expired at {1}",
key, DateTime.Now.ToShortDateString() + " " +
DateTime.Now.ToShortTimeString()) + "\nRefreshing Cache: " +
lcHtml;
SmtpClient smtp = new SmtpClient("mercury.utg.uvn.net");
mail.IsBodyHtml = false;
try
{
smtp.Send(mail);
}
catch (Exception ex)
{
ErrHandler.WriteError(ex.Message + "\n" +
ex.StackTrace.ToString());
LogUtil.LogDebugMessages(ex.Message + ":" +
ex.StackTrace.ToString());
}
}
}
for some reason, when I go to the page. Someone times the data is cached and sometimes it is not. Is there something wrong here
I tried app fabric but since the server does not have iis 7 I am not able to use that
Looks to me like you may have a race condition in your RefreshCache call. Check out this great answer for suggestions on how to handle synchronization:
C# version of java's synchronized keyword?
If I were you, I'd simplify my code. You only really need:
when the application starts up, load the cache
when the cache expires, reload it
if a user tries to access the cached object and misses, sleep their thread for a second and check again
The amount of data you can get into the cache may be the issue.
If the cache is full then the data will obviously not be cached.
You can check your memory allocation using the process monitor, have a look in "Cache Total Entries."

Categories

Resources