RestSharp - when a test runs for the first time, it fails. When I debug, it passes. what's going on? - asp.net-web-api

Pretty basic test:
[TestClass]
public class ApiClientTest
{
private RestClient _client;
[TestInitialize()]
public virtual void TestInitialize()
{
_client = new RestClient("http://localhost:24144");
_client.CookieContainer = new System.Net.CookieContainer();
}
[TestMethod]
public void ApiClientTestCRUD()
{
// 1. Log out twice. Verify Unauthorized.
var response = LogOut();
response = LogOut();
Assert.AreEqual(response.StatusCode, HttpStatusCode.Unauthorized);
// Error here:
Result Message: Assert.AreEqual failed. Expected:<0>.
Actual:< Unauthorized >.
I get <0>, which isn't even something that my WebAPI returns.
I think the issue is with my use of RestSharp, because if I debug one time it passes, and then subsequent runs pass. Any clue what's going on?
To be clear - this occurs when I open up my solution and attempt to run the test for the first time. I can fix it by debugging once, watching it pass, and then running without debugging as much as I want. I can reproduce this by closing VS and opening up the solution again - and running the test without debugging first.
Here's the LogOut method in my WebAPI:
[Authorize]
public HttpResponseMessage LogOut()
{
try
{
if (User.Identity.IsAuthenticated)
{
WebSecurity.Logout();
return Request.CreateResponse(HttpStatusCode.OK, "logged out successfully.");
}
return Request.CreateResponse(HttpStatusCode.Conflict, "already done.");
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
UPDATE:
I ended up running the tests with Trace.WriteLine:
// 1. Log out twice. Verify Unauthorized.
Trace.WriteLine("ENTERING FIRST LOGOUT");
var response = LogOut();
Trace.WriteLine("Content: " + response.Content);
Trace.WriteLine("ErrorMessage: " + response.ErrorMessage);
Trace.WriteLine("ResponseStatus: " + response.ResponseStatus);
Trace.WriteLine("StatusCode: " + response.StatusCode);
Trace.WriteLine("StatusDescription: " + response.StatusDescription);
response = LogOut();
Trace.WriteLine("COMPLETED LOGOUTS");
Assert.AreEqual(response.StatusCode, HttpStatusCode.Unauthorized);
And I found the following:
ENTERING FIRST LOGOUT
Content:
ErrorMessage: Unable to connect to the remote server
ResponseStatus: Error
StatusCode: 0
StatusDescription:
COMPLETED LOGOUTS
My solution has a test project with this RestSharp test, and a WebAPI project that's supposed to be accepting these requests. If I debug, the RestClient connects. If not, it times out. Any tips?

When debugging is not possible to solve the problem go to the old fashion way.
Add Trace.WriteLine (or even append text to a C:\temp.txt file).
Write some string before every return in the LogOut method, then try writing some more information (if it's the last return then write the Exception message, if it's the second return write the Identity information.
Hope this helps.

How are you hosting the server? I see this that you're using port 24144. Maybe in debug mode you're running the express IIS Web Server and that's the port, but in non-debug mode it's not?

Related

JSon seralization error with Web Api

I was getting a self referenceing loop error "Self referencing loop detected for property 'ApplicationInstance' with type 'ASP.global_asax'" returned from a PUT call to a web api.
I added this to the web api config:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All;
Now I get a different error:
"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8
InnerException":ExceptionMessage":"Error getting value from 'ReadTimeout' on 'System.Web.HttpInputStream'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":" at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)...
Per suggestion, I added the ".ReferenceLoopHandling.Ignore;" config. This fixesd the loop error, but not the 'can't read value' error.
I am having some trouble finding a cure for this one.
EDIT - Error is gone. I am hesitant to say yet if it is fixed, because I am not yet sure why the error was there in the first place. I made the error leave by changing my Put code in the web api. It was:
[HttpPut]
public IHttpActionResult Put([FromBody]RecipientDTO recipient)
{
try
{
repo.SaveUpdatedRecipient(recipient);
return Ok(this.GetById(recipient.RecipKey));
}
catch (Exception ex)
{
return BadRequest(ex.ToString());
}
}
and is now:
[HttpPut]
public HttpResponseMessage Put([FromBody]RecipientDTO recipient)
{
try
{
repo.SaveUpdatedRecipient(recipient);
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (Exception ex)
{
ex.ToString();
//ValidationMethods.GetDbValidationExceptions(ex);
return Request.CreateResponse(HttpStatusCode.NotFound);
}
}
I am still working on the error handling portion, but at least the error is gone and the data is saved. I will update when I find out more. Any input is welcome.
To solve the issue add the below line of code to WebApiConfig.cs file in your webapi project
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

404 error when using https with signalR

I am using signalR over https and I have seeming done everything off this site:
https://weblog.west-wind.com/posts/2013/Sep/23/Hosting-SignalR-under-SSLhttps
Yet, I am still getting a 404 error when I signalr is trying to connect.
https://localhost:9000//negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22logshub%22%7D%5D&_=1438785507850 404 (Not Found)
This is my OWIN startup program starting on https://*:9000
class Program
{
static void Main(string[] args)
{
string dbFile = "logDB.sqlite";
if (!File.Exists(dbFile))
{
SQLiteDataProviderCreator.Create();
SQLiteDataProviderCreator.CreateDataBase();
}
IDataProvider provider = new SQLiteDataProvider("Data Source=logdb.sqlite;Version=3;PRAGMA journal_mode=WAL;Pooling=True;Max Pool Size=100;");
LogsModule.Provider = provider;
using (WebApp.Start<Startup>("https://*:9000/"))
{
Console.WriteLine("Launched site on Port 9000");
Console.WriteLine("Press [enter] to quit...");
Console.ReadLine();
}
}
}
And here the javascript that is supposed to allow it to connect over https.
var hubUrl = "https://localhost:9000/signalr";
$.connection.hub.url = hubUrl;
$.connection.hub.logging = true;
I also created a cert using makecert and bound it to the endpoint 0.0.0.0:9000.
Had a similar issue where I had to run the program as administrator.
For anyone else that comes across this.
The hubUrl should normally be:
var hubUrl = "https://localhost:9000/signalr/hubs";
This is even shown in the link provided.
Also, needs to ensure that the hub script is loaded prior to this script:
<script src='https://localhost:9000/signalr/hubs'></script>

JUnit needs special permissions?

My builds have been failing due to some of the integration tests I've been running. I'm stuck on why it won't work. Here is an example of the output:
I'm using Maven to first build, then it calls the JUnit tests. I'm seeing this 401 Unauthorized message in every single test, and I believe that's what is causing the builds to fail. In my mind, this means there are some permissions / authentication parameters that need to be set. Where would I go about doing this in JUnit?
Edit
#Test
public void testXmlHorsesNonRunners() throws Exception {
String servletUrl = SERVER + "sd/date/2013-01-13/horses/nonrunners";
Document results = issueRequest(servletUrl, APPLICATION_XML, false);
assertNotNull(results);
// debugDocument(results, "NonRunners");
String count = getXPathStringValue(
"string(count(hrdg:data/hrdg:meeting/hrdg:event/hrdg:nonrunner/hrdg:selection))",
results);
assertEquals("non runners", "45", count);
}
If you can, try to ignore the detail. Effectively, this is making a request. This is a sample of a test that uses the issueRequest method. This method is what makes HTTP requests. (This is a big method, which is why I didn't post it originally. I'll try to make it as readable as possible.
logger.info("Sending request: " + servletUrl);
HttpGet httpGet = null;
// InputStream is = null;
DefaultHttpClient httpclient = null;
try {
httpclient = new DefaultHttpClient();
doFormLogin(httpclient, servletUrl, acceptMime, isIrishUser);
httpGet = new HttpGet(servletUrl);
httpGet.addHeader("accept", acceptMime);
// but more importantly now add the user agent header
setUserAgent(httpGet, acceptMime);
logger.info("executing request" + httpGet.getRequestLine());
// Execute the request
HttpResponse response = httpclient.execute(httpGet);
// Examine the response status
StatusLine statusLine = response.getStatusLine();
logger.info(statusLine);
switch (statusLine.getStatusCode()) {
case 401:
throw new HttpResponseException(statusLine.getStatusCode(),
"Unauthorized");
case 403:
throw new HttpResponseException(statusLine.getStatusCode(),
"Forbidden");
case 404:
throw new HttpResponseException(statusLine.getStatusCode(),
"Not Found");
default:
if (300 < statusLine.getStatusCode()) {
throw new HttpResponseException(statusLine.getStatusCode(),
"Unexpected Error");
}
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
Document doc = null;
if (entity != null) {
InputStream instream = entity.getContent();
try {
// debugContent(instream);
doc = documentBuilder.parse(instream);
} catch (IOException ex) {
// In case of an IOException the connection will be released
// back to the connection manager automatically
throw ex;
} catch (RuntimeException ex) {
// In case of an unexpected exception you may want to abort
// the HTTP request in order to shut down the underlying
// connection and release it back to the connection manager.
httpGet.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
instream.close();
}
}
return doc;
} finally {
// Release the connection.
closeConnection(httpclient);
}
I notice that your test output shows HTTP/1.1 500 Internal Server Error a couple of lines before the 401 error. I wonder if the root cause could be hiding in there. If I were you I'd try looking for more details about what error happened on the server at that point in the test, to see if it could be responsible for the authentication problem (maybe the failure is in a login controller of some sort, or is causing a session to be cancelled?)
Alternately: it looks like you're using the Apache HttpClient library to do the request, inside the issueRequest method. If you need to include authentication credentials in the request, that would be the code you'd need to change. Here's an example of doing HTTP Basic authentication in HttpClient, if that helps. (And more examples, if that one doesn't.)
(I'd second the observation that this problem probably isn't specific to JUnit. If you need to do more research, I'd suggest learning more about HttpClient, and about what this app expects the browser to send. One possibility: use something like Chrome Dev Tools to peek at your communications with the server when you do this manually, and see if there's anything important that the test isn't doing, or is doing differently.
Once you've figured out how to login, it might make sense to do it in a #Before method in your JUnit test.)
HTTP permission denied has nothing to do with JUnit. You probably need to set your credentials while making the request in the code itself. Show us some code.
Also, unit testing is not really meant to access the internet. Its purpose is for testing small, concise parts of your code which shouldn't rely on any external factors. Integration tests should cover that.
If you can, try to mock your network requests using EasyMock or PowerMock and make them return a resource you would load from your local resources folder (e.g. test/resources).

FTP status code response don't work

Welcome!
I have a little problem with own application. This app can be connect(sith socket) an FTP server, and its work fine. But my problem is, if the user use bad usernam or password, the program won't receive the response statucode. Whats wrong?
I would like to use this statuscode some clause to examine(usernem or/and password etc.)
Code:
public static void ReadResponse()
{
result = ParseHostResponse();
statusCode = int.Parse(result.Substring(0, 3));
statusMessage = "";
}
The ParseHostResponse() method contains next:
Code:
public static string ParseHostResponse()
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = socket.RemoteEndPoint;
socketEventArg.SetBuffer(buffer, BUFFER_SIZE, 0);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
statusMessage = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
statusMessage = statusMessage.Trim('\0');
}
else
{
statusMessage = e.SocketError.ToString();
}
});
socket.ReceiveAsync(socketEventArg);
string[] msg = statusMessage.Split('\n');
if (statusMessage.Length > 2)
{
statusMessage = msg[msg.Length - 2];
}
else
{
statusMessage = msg[0];
}
if (!statusMessage.Substring(3, 1).Equals(" "))
{
return ParseHostResponse();
}
return statusMessage;
}
If I invite to the ReadResponse() method, the Visual Studio answer with this exception: NullReferenceException
in this code:
Code:
.
.
string[] msg = statusMessage.Split('\n');
.
What is the wrong? This code issue to http://msdn.microsoft.com/en-us/library/hh202858%28v=vs.92%29.aspx#BKMK_RECEIVING
Thank you for your help!
I can't help, but have to start with these side remarks:
statusMessage.Trim('\0') does not work (try it)
statusMessage.Split('\n') is inefficient as it involves extra allocations (guess why)
Now to the actual subject: I never used sockets on WP7, but from what I know about async operations it looks to me that you start async op (by calling ReceiveAsync) and use the result (statusMessage) before the answer arrives.
Think a bit about your design of the ParseHostResponse() method:
Bad name: Indicates parsing of a response, while it actually performs communication
Bad functionality: The method indicates sync patter, but internally uses async pattern. I don't know what to suggest here as every solution seems to be wrong. For example waiting for a response will make UI irresposible.
My main recommendation is that you get more information about async programming and then reprogramm your app accordingly.

SmtpClient.SendAsync blocking my ASP.NET MVC Request

I have a Action that sends a simple email:
[HttpPost, ActionName("Index")]
public ActionResult IndexPost(ContactForm contactForm)
{
if (ModelState.IsValid)
{
new EmailService().SendAsync(contactForm.Email, contactForm.Name, contactForm.Subject, contactForm.Body, true);
return RedirectToAction(MVC.Contact.Success());
}
return View(contactForm);
}
And a email service:
public void SendAsync(string fromEmail, string fromName, string subject, string body, bool isBodyHtml)
{
MailMessage mailMessage....
....
SmtpClient client = new SmtpClient(settingRepository.SmtpAddress, settingRepository.SmtpPort);
client.EnableSsl = settingRepository.SmtpSsl;
client.Credentials = new NetworkCredential(settingRepository.SmtpUserName, settingRepository.SmtpPassword);
client.SendCompleted += client_SendCompleted;
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage));
}
private void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
Tuple<SmtpClient, MailMessage> data = (Tuple<SmtpClient, MailMessage>)e.UserState;
data.Item1.Dispose();
data.Item2.Dispose();
if (e.Error != null)
{
}
}
When I send a email, I am using Async method, then my method SendAsync return immediately, then RedirectToAction is called. But the response(in this case a redirect) isnĀ“t sent by ASP.NET until client_SendCompleted is completed.
Here's what I'm trying to understand:
When watching the execution in Visual Studio debugger, the SendAsync returns immediately (and RedirectToAction is called), but nothing happens in the browser until email is sent?
If i put a breakpoint inside client_SendCompleted, the client stay at loading.... until I hit F5 at debugger.
This is by design. ASP.NET will automatically wait for any outstanding async work to finish before finishing the request if the async work was kicked off in a way that calls into the underlying SynchronizationContext. This is to ensure that if your async operation tries to interact with the HttpContext, HttpResponse, etc. it will still be around.
If you want to do true fire & forget, you need to wrap your call in ThreadPool.QueueUserWorkItem. This will force it to run on a new thread pool thread without going through the SynchronizationContext, so the request will then happily return.
Note however, that if for any reason the app domain were to go down while your send was still in progress (e.g. if you changed the web.config file, dropped a new file into bin, the app pool recycled, etc.) your async send would be abruptly interrupted. If you care about that, take a look at Phil Haacks WebBackgrounder for ASP.NET, which let's you queue and run background work (like sending an email) in such a way that will ensure it gracefully finishes in the case the app domain shuts down.
This is an interesting one. I've reproduced the unexpected behaviour, but I can't explain it. I'll keep digging.
Anyway the solution seems to be to queue a background thread, which kind of defeats the purpose in using SendAsync. You end up with this:
MailMessage mailMessage = new MailMessage(...);
SmtpClient client = new SmtpClient(...);
client.SendCompleted += (s, e) =>
{
client.Dispose();
mailMessage.Dispose();
};
ThreadPool.QueueUserWorkItem(o =>
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage)));
Which may as well become:
ThreadPool.QueueUserWorkItem(o => {
using (SmtpClient client = new SmtpClient(...))
{
using (MailMessage mailMessage = new MailMessage(...))
{
client.Send(mailMessage, Tuple.Create(client, mailMessage));
}
}
});
With .Net 4.5.2, you can do this with ActionMailer.Net:
var mailer = new MailController();
var msg = mailer.SomeMailAction(recipient);
var tcs = new TaskCompletionSource<MailMessage>();
mailer.OnMailSentCallback = tcs.SetResult;
HostingEnvironment.QueueBackgroundWorkItem(async ct =>
{
msg.DeliverAsync();
await tcs.Task;
Trace.TraceInformation("Mail sent to " + recipient);
});
Please read this first: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
I sent the bug to Microsoft Connect https://connect.microsoft.com/VisualStudio/feedback/details/688210/smtpclient-sendasync-blocking-my-asp-net-mvc-request

Resources