Ok so this is driving me nuts. I am probably tired and the answer is looking at me.
public ActionResult _Login(LoginViewModel loginViewModel)
{
if (User.Identity.IsAuthenticated)
{
return JavaScript("window.location=" + "'" + loginViewModel.ReturntUrl + "'");
}
if (ModelState.IsValid)
{
if (Session["loginCount"] == null) //setup the session var with 0 count
{
Session.Add("loginCount", 0);
}
_loginStatus = _authenticationService.Authenticate(loginViewModel.SiteLoginViewModel.EmailAddress,
loginViewModel.SiteLoginViewModel.Password);
if(!_loginStatus.UserExists)
{
ModelState.AddModelError("SiteLoginViewModel.EmailAddress", _loginStatus.ErrorMessage);
return PartialView();
}
// This will only be true if the user types in the correct password
if(!_loginStatus.IsAuthenticated)
{
Session["loginCount"] = (int)Session["loginCount"] + 1;
Response.Write(Session["loginCount"]); // Counter is incremented twice!!!!
//_userService.SetInvalidLoginAttempts(loginViewModel.SiteLoginViewModel.EmailAddress, 1);
ModelState.AddModelError("SiteLoginViewModel.EmailAddress", _loginStatus.ErrorMessage);
return PartialView();
}
// DELETE ANY OPENID Cookies
var openidCookie = new HttpCookie("openid_provider");
if (openidCookie.Value != null)
{
openidCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(openidCookie);
}
_userService.SetInvalidLoginAttempts(loginViewModel.SiteLoginViewModel.EmailAddress, 0);
SetAuthTicket(loginViewModel.SiteLoginViewModel.EmailAddress, _userService.GetUserId(loginViewModel.SiteLoginViewModel.EmailAddress),
loginViewModel.SiteLoginViewModel.RemeberLogin);
if (!string.IsNullOrEmpty(loginViewModel.ReturntUrl))
{
return JavaScript("window.location=" + "'" + loginViewModel.ReturntUrl + "'");
}
return JavaScript("location.reload(true)");
}
return PartialView();
}
This almost seems that the request is being processed twice however when i step through with the debugger I only see it once. Please ignore the non important parts of the ActionMethod
This looks like you are tying to code for stuff that you automatically get with .Net's Membership provider.
Your first line "User.Identity.IsAuthenticated" looks like you are using part of membership provider but it would seem the rest is trying to code around it.
Also, why are you returning javascript to direct the user's browser to a new URL? Regarless of what .net platform you are on there are plenty of ways to redirect the user's browser without having to return raw javascript, which in my book is REALLY BAD.
##
This fixed the problem and will be removed rather than commented out. Including this twice is very bad obviously :)
Related
I have a service which uses a Yahoo! Finance table yahoo.finance.xchange. This morning I noticed it has stopped working because suddenly Yahoo! started to return an error saying:
{
"error": {
"lang": "en-US",
"description": "No definition found for Table yahoo.finance.xchange"
}
}
This is the request URL. Interesting fact: if I try to refresh the query multiple times, sometimes I get back a correct response but this happen very rarely (like 10% of the time). Days before, everything was fine.
Does this mean Yahoo API is down or am I missing something because the API was changed? I would appreciate any help.
Since I have the same problem and that it started today too, that others came to post exactly in the same time as well, and that it still works most of the time, the only explanation I can find is that they have some random database errors on their end and we can hope that this will be solved soon. I also have a 20% rate of failures when refreshing the page of the query.
My guess is that they use many servers to handle the requests (let's say 8) and that one of them is empty or doesn't have that table for some reasons so whenever it directs the query to that server, the error is returned.
Temporary solution: Just modify your script to retry 3-4 times. That did it for me because among 5 attempts at least one succeeds.
I solve this issue by using quote.yahoo.com instead of the query.yahooapis.com service. Here's my code:
function devise($currency_from,$currency_to,$amount_from){
$url = "http://quote.yahoo.com/d/quotes.csv?s=" . $currency_from . $currency_to . "=X" . "&f=l1&e=.csv";
$handle = fopen($url, "r");
$exchange_rate = fread($handle, 2000);
fclose($handle );
$amount_to = $amount_from * $exchange_rate;
return round($amount_to,2);
}
EDIT the above no longer works. At this point, lets just forget about yahoo lol Use this instead
function convertCurrency($from, $to, $amount)
{
$url = file_get_contents('https://free.currencyconverterapi.com/api/v5/convert?q=' . $from . '_' . $to . '&compact=ultra');
$json = json_decode($url, true);
$rate = implode(" ",$json);
$total = $rate * $amount;
$rounded = round($total);
return $total;
}
Same error, i migrate to http://finance.yahoo.com
Here is C# example
private static readonly ILog Log = LogManager.GetCurrentClassLogger();
private int YahooTimeOut = 4000;
private int Try { get; set; }
public decimal GetRate(string from, string to)
{
var url =
string.Format(
"http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={0}{1}=X", from, to);
var request = (HttpWebRequest)WebRequest.Create(url);
request.UseDefaultCredentials = true;
request.ContentType = "text/csv";
request.Timeout = YahooTimeOut;
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
var resStream = response.GetResponseStream();
using (var reader = new StreamReader(resStream))
{
var html = reader.ReadToEnd();
var values = Regex.Split(html, ",");
var rate = Convert.ToDecimal(values[1], new CultureInfo("en-US"));
if (rate == 0)
{
Thread.Sleep(550);
++Try;
return Try < 5 ? GetRate(from, to) : 0;
}
return rate;
}
}
}
catch (Exception ex)
{
Log.Warning("Get currency rate from Yahoo fail " + ex);
Thread.Sleep(550);
++Try;
return Try < 5 ? GetRate(from, to) : 0;
}
}
I've got the same issue.
I need exchange rates in my app, so I decided to use currencylayer.com API instead - they give 168 currencies, including precious metals and Bitcoin.
I've also written a microservice using webtask.io to cache rates from currencylayer and do cross-rate calculations.
And I've written a blog post about it 🤓
Check it out if you want to run your own microservice, it's pretty easy 😉
I found solution, in my case, just change http to https and everything works fine.
I have configured a listener on kernel.request which sets a new response with redirect when the session time has reached a certain value. The listener works fine and redirects to a certain page, on the next request, after the session has ended. But my problem is on the page I have many links and if I press multiple times the same link, the initial request with the redirect is cancelled/stopped and a new request is made with the last link pressed and so it passes my redirect even though the session has ended and is destroyed. So, my question is how to prevent additional requests/link presses after the firs request is made?
Here is my code:
public function onKernelRequestSession(GetResponseEvent $event)
{
$request = $event->getRequest();
$route = $request->get('_route');
$session = $request->getSession();
if ((false === strpos($route, '_wdt')) && ($route != null)) {
$session->start();
$time = time() - $session->getMetadataBag()->getCreated();
if ($route != 'main_route_for_idle_page') {
if (!$session->get("active") && $route == 'main_route_for_site_pages') {
$session->invalidate();
$session->set("active", "1");
} else {
if ($time >= $this->sessionTime) {
$session->clear();
$session->invalidate();
$event->setResponse(new RedirectResponse($this->router->generate('main_route_for_idle_page')));
}
}
} else {
if ($session->get("activ")) {
$session->clear();
$session->invalidate();
}
}
}
}
Thak you.
Idea #1: Simple incremental counter
Each request sends sequence number as param which is being verified as expected at the server.
Server increments the number and sends it back via response
the new number is used in future requests
Basically, if server expects the SEQUENCE number to be 2 and client sends 1 the request is to be rejected.
Idea #2: Unique hash each time
Similar to the idea above, but uses unique hashes to eliminate predictive nature of incremental sequence.
I resolved the issue using JQuery: when a link was pressed I disabled the other ones and so only one request is made from the page:
var isClicked = false;
$(".menu-link").click(function(e) {
if(!isClicked) {
isClicked = true;
} else {
e.preventDefault();
}
});
Thanks.
I have had this for a couple of days now.
I have a simple search form. When form is submitted the server searches for some data from another server and return data to the screen. When the submit completes it gets some javascript from the server based on the results returned from the search. the javascript then makes multiple concurrent jquery get requests, lets say 4, to the asp.net mvc3 webapp.
I have demonstrated that all the get requests fire at the same time in Firebug but when debugging my app with VS the breakpoints only get hit once the previous request completes.
The actions are the same but the querys are different; ie
/Home/Details/040801
/Home/Details/040802
/Home/Details/040803
So these are different URLs and, from what i found out, FF should treat them differently.
So my questions are:
Am I missing something obvious?
Does IIS have some funny blocking on the same route?
Is it a session cache issue? I am locking lock (lockobject){} on writes to the common session variables.
Im not using ViewBag or TempData.
The page load times, even when everything is cached in the Session, are still noticeably synchronous.
Windows Server 2008 R2
Using IIS 7.5
ASP.NET MVC 3
VS2010 Chrome or FF browser
I have my routes set up as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute("Details", "{controller}/{action}/{id}/{booking}", new { id = UrlParameter.Optional, booking = UrlParameter.Optional});
Nothing special there as you can see.
Sample code from one of the blocked routes:
public ActionResult Details(string id, bool booking = false)
{
if (booking)
{
return BookingDetails(id, true);
}
Dictionary<string, FlightDetails> detailDic;
string scenarioInput;
lock (DetailsLock)
{
if (Session["DetailDic"] == null)
{
Session["DetailDic"] = new Dictionary<string, FlightDetails>();
}
detailDic = (Dictionary<string, FlightDetails>)Session["DetailDic"];
}
if (detailDic.ContainsKey(id))
{
return PartialView("Details", detailDic[id]);
}
lock (GuidLock)
{
if (Session["DetailGuids"] == null)
{
Session["DetailGuids"] = new Dictionary<string, string>();
}
scenarioInput = ((Dictionary<string, string>)Session["DetailGuids"])[id];
}
// query results list
string queryText = string.Format("<View><Query><Where><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">OUT {0}</Value></Eq></Where></Query></View>", scenarioInput);
ListItemCollection oList;
int counter = 0;
do
{
oList = SharepointHelper.GetListFromSharepoint("ListName", queryText, ClientContext);
counter++;
Thread.Sleep(1000);
} while (oList.Count == 0 && counter <= Timeout);
if (oList.Count == 0)
{
return PartialView("Details", (object)null);
}
var item = oList[0];
FlightDetails flightDetails = CreateFlightDetails(id, scenarioInput, item);
lock (DetailsLock)
{
detailDic.Add(id, flightDetails);
}
return PartialView("Details", flightDetails);
}
when using session object in server-side your async calls wait for session object released by other request. Becuase of this async ajax calls act like sync. You have to use session as readonly in that action.
Add this attribute to action you call if you dont write anything to session.
[SessionState(SessionStateBehavior.ReadOnly)]
We have a CI installation that has the following setting in our config...
$config['enable_query_strings'] = TRUE;
We need this in order for another area of our application to run correctly with a third party API. What's happening, however, is that pagination is defaulting to a query string method of doing pagination, which doesn't play well with caching.
Right now, they look like this...
http://localhost/something/?&page=6
It's not playing well with caching, mainly because every page URL is the same page to CI. My goal is to get switched over to the below example without messing with global settings for the rest of my application.
I've been trying for hours to find a way to disable the above setting only within this single part of the application, so that we can properly have separate URLs for the pagination, like this...
http://localhost/something/1
http://localhost/something/2
http://localhost/something/3
So far, I have been unable to overide that setting for this controller, and honestly, I'm not sure there's even a way to actually do it. Any help is appreciated. There's got to be some method of disabling a feature for a single controller somehow.
Could you use routing?
$route['something/page/(:num)'] = "something?&page=$1";
edit: to turn off pagination query strings with $config['enable_query_strings'] = TRUE;
system/libraries/Pagination.php
~line 134
change
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
if ($CI->input->get($this->query_string_segment) != 0)
{
$this->cur_page = $CI->input->get($this->query_string_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}
else
{
if ($CI->uri->segment($this->uri_segment) != 0)
{
$this->cur_page = $CI->uri->segment($this->uri_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}
to
if ($CI->uri->segment($this->uri_segment) != 0)
{
$this->cur_page = $CI->uri->segment($this->uri_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
~line 196
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
$this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'=';
}
else
{
$this->base_url = rtrim($this->base_url, '/') .'/';
}
to
$this->base_url = rtrim($this->base_url, '/') .'/';
that might do it. Or maybe better form would be to hook into the page...
Simple solution...
$this->config->set_item('enable_query_strings',FALSE);
Just put this before you call your pagination logic in the controller. Thanks go to Taftse in the #codeigniter IRC channel for this simple override.
I am using Ajax to post data to the server(PHP code) and update it. i am posting many data one after the other, but in between the Ajax post fails and dont return a readyState to 4.
the code is as follows
function getHttpRequest()
{
var request=false;
if(window.XMLHttpRequest)
{
request=new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
try
{
request=new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e)
{
try
{
request=new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e)
{
request=false;
}
}
}
return request;
}
the code begins here..
function updateAnswer(){
var request=getHttpRequest();
request.open('post','addAnswer.php');
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
request.send("answer="+ans);
if(request.readyState == 4)
{
var response=request.responseText;
document.getElementById("display").innerHTML=response;
}
}
i call this function to update answer in database but it donot return status=4 sometimes... please help
innerinnerHTML should be innerHTML. updateAnswer gets called each time readyState is changing from zero to four. Four is fully loaded, while those lesser are different loading stages.
Why not make life easier and use a framework like jQuery?
Also, can't you post all the data at once, in that way save a few roundtrips to the server?