Ho un progetto ASP.NET che prevede l'invio di richieste HTTP tramite il framework API Web. La seguente eccezione viene sollevata solo durante il debug:WebException su richiesta HTTP durante il debug
Il server ha commesso una violazione del protocollo. Section = ResponseStatusLine
Il progetto funziona perfettamente se "Avvia senza debug".
Come devo risolvere questa eccezione?
Qualsiasi aiuto è apprezzato!
Aggiornamento
Il problema sembra legato alla ASP.NET MVC Identity Framework.
per accedere ad altri metodi di Web-API, l'applicazione client deve POST prima un login richiesta (la richiesta di accesso non ha bisogno di essere ancora sicuro, e così io mando le corde username e password direttamente al Web -Punto POST API). Se commento la richiesta di accesso, non viene sollevata alcuna eccezione.
Qui di seguito sono i frammenti di codice in materia:
il metodo POST:
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
AccountAccess ac = new AccountAccess();
public async Task<HttpResponseMessage> Post()
{
string result = await Request.Content.ReadAsStringAsync();
LoginMessage msg = JsonConvert.DeserializeObject<LoginMessage>(result);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var user = UserManager.Find(msg.username, msg.password);
if (user == null)
return response;
if (user.Roles == null)
return response;
var role = from r in user.Roles where (r.RoleId == "1" || r.RoleId == "2") select r;
if (role.Count() == 0)
{
return response;
}
bool task = await ac.LoginAsync(msg.username, msg.password);
response.Content = new StringContent(task.ToString());
return response;
}
La classe account di accesso (simulando l'AccountController default nel modello MVC):
public class AccountAccess
{
public static bool success = false;
public AccountAccess()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountAccess(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
public UserManager<ApplicationUser> UserManager { get; private set; }
public async Task<bool> LoginAsync(string username, string password)
{
var user = await UserManager.FindAsync(username, password);
if (user != null)
{
await SignInAsync(user, isPersistent: false);
return true;
}
else
{
return false;
}
}
~AccountAccess()
{
if (UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
}
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.Current.GetOwinContext().Authentication;
}
}
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
}
Qui di seguito sono i frammenti importanti di codice:
In applicazione client:
public static async Task<List<T>> getItemAsync<T>(string urlAction)
{
message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.RequestUri = new Uri(urlBase + urlAction);
HttpResponseMessage response = await client.SendAsync(message);
string result = await response.Content.ReadAsStringAsync();
List<T> msgs = JsonConvert.DeserializeObject<List<T>>(result);
return msgs;
}
Nel controller Web-API:
public HttpResponseMessage Get(string id)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
if (id == "ItemA")
{
List<ItemAMessage> msgs = new List<ItemAMessage>();
// some code...
response.Content = new StringContent(JsonConvert.SerializeObject(msgs));
}
else if (id == "ItemB")
{
List<ItemBMessage> msgs = new List<ItemBMessage>();
// some code...
response.Content = new StringContent(JsonConvert.SerializeObject(msgs));
}
return response;
}
alcune osservazioni che ho:
- I t ho pensato che potrei aver bisogno di inviare la richiesta in modo asincrono (con la sintassi
async-await
), ma l'eccezione persiste in questo modo. - Se passo il codice, la richiesta fa immette il metodo HTTP, ma il codice si interrompe in corrispondenza della riga casuale (Perché ?!) prima di restituire la risposta, quindi presumo che non venga inviata alcuna risposta.
- Ho provato le seguenti soluzioni, come suggerito in risposte a domande simili, nessuno dei quali lavora per me:
- Impostazione
useUnsafeHeaderParsing
atrue
- Aggiunta l'intestazione
Keep-Alive: false
- Cambiare l'impostazione della porta di Skype (non ho Skype, e la porta 80 e 443 non sono occupati)
- Impostazione
Ulteriori informazioni rmazioni, nel caso in cui la materia:
- Mac OS con sistema operativo Windows 8.1 con VMware Fusion
- Visual Studio 2013
- .NET Framework 4.5
- IIS Express Server
Aggiornamento 2
L'eccezione è stata risolta, ma non sono sicuro di quale modifica abbia funzionato. Per quanto ne so, uno o entrambi i seguenti fisso è:
- Ho un metodo
checkConnection()
, che invia in pratica una richiesta GET e tornare vero in caso di successo. Ho aggiuntoawait
al metodoHttpClient.SendAsync()
e applicato async fino a. - Ho ritirato tutto il codice nel costruttore MainWindow, ad eccezione del metodo
InitializeComponent()
, nel gestore eventi Inizializzazione finestra.
Qualche idea?
Questi sono codice relativo alle modifiche illustrate sopra:
metodo checkConnectionAsync:
public static async Task<bool> checkConnectionAsync()
{
message = new HttpRequestMessage();
message.Method = HttpMethod.Get;
message.RequestUri = new Uri(urlBase);
try
{
HttpResponseMessage response = await client.SendAsync(message);
return (response.IsSuccessStatusCode);
}
catch (AggregateException)
{
return false;
}
}
Finestra gestore eventi inizializzata (retratto dal costruttore MainWindow):
private async void Window_Initialized(object sender, EventArgs e)
{
if (await checkConnectionAsync())
{
await loggingIn();
getItemA();
getItemB();
}
else
{
logMsg.Content = "Connection Lost. Restart GUI and try again.";
}
}
Update 3
Anche se questo può essere un po 'off-topic, vorrei aggiungere una nota a margine in caso qualcuno altro cade in questo - ho utilizzato il metodo di autenticazione sbagliato per Web-API iniziare con. Il modello di progetto Web-API dispone già di un framework Identity incorporato e in qualche modo "lo sostituisco" con un approccio piuttosto semplice ma interrotto ...
This video è un bel tutorial per iniziare.
This article fornisce una spiegazione più completa.
Cosa succede se si rimuove la chiamata a riposo in LoginAsync? –
@Brianfromstatefarm In realtà ho aggiunto questa riga per testare qualcos'altro e ho dimenticato di rimuoverlo durante la pubblicazione del codice. Grazie per aver segnalato! –
È possibile che la VM stia aggiungendo al problema? –