force singleordefault to execute - asp.net-mvc-4

Can anyone tell me why the following code does not work in an api controller (MVC4)? I get an error saying that the "Cannot access a disposed object". I found that in other cases there should be a call to ToList() so that it forces the query to be executed. But in my case, I'm using SingleOrDefault(), isn't this executed on the database right away?
public HttpResponseMessage GetPurchaseOrder(int POId)
{
PurchaseOrder po;
HttpResponseMessage resp;
using (PMDataDataContext database = new PMDataDataContext())
{
po = database.PurchaseOrders.SingleOrDefault(x => x.POId == POId);
if (po == null)
{
var message = string.Format("id = {0} not found", POId);
HttpError err = new HttpError(message);
resp = Request.CreateResponse(HttpStatusCode.NotFound, err);
}
else
{
resp = Request.CreateResponse(HttpStatusCode.OK, po);
}
}
return resp;
}

Yes, but if you have any lazy-loaded properties in PurchaseOrder, when Web API tries to serialize the object, EF will try to fetch the data from the database and for this the context will be needed but it will not be available.

Try it so that the context to database gets disposed right after the query. SingleOrDefault should send the query to the database immediately.
public HttpResponseMessage GetPurchaseOrder(int POId)
{
PurchaseOrder po;
HttpResponseMessage resp;
using (PMDataDataContext database = new PMDataDataContext())
{
po = database.PurchaseOrders.SingleOrDefault(x => x.POId == POId);
}
if (po == null)
{
var message = string.Format("id = {0} not found", POId);
HttpError err = new HttpError(message);
resp = Request.CreateResponse(HttpStatusCode.NotFound, err);
}
else
{
resp = Request.CreateResponse(HttpStatusCode.OK, po);
}
return resp;
}

Badri led me to solve my problem. When I placed a breakpoint in my code and followed in debug mode, it seemed that one of the associated objects needed the context to be fetched. The property PurchaseOrder.Item.ItemCategory was giving an ObjectDisposedException, when I was looking at the related properties.
I solved it by placing database.DeferredLoadingEnabled = false right before fetching the po using the SingleOrDefault call.

Related

UnityWebRequest Get api call returns connection error

So I am trying to do the Get method call to retrieve data from api server.The problem I am getting is that in Unity Editor, Both Get and Post method works perfectly fine, but in the webgl build only post method works whereas Get method returns 500 as error code and webrequest.error as Connection Error.Is there any workaround for this.
public IEnumerator GetPlayerData()
{
Debug.Log("This is Working");
string url = "https:my api";
Authorization playerData = new Authorization();
playerData.walletaddress = PlayerPrefs.GetString("Account");
playerData.table = "userdata";
string jsonStringTrial = JsonUtility.ToJson(playerData);
using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
{
Debug.Log("This is also Working");
webRequest.method = UnityWebRequest.kHttpVerbGET;;
webRequest.SetRequestHeader("Content-Type", "application/json");
webRequest.SetRequestHeader("Accept", "application/json");
webRequest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(jsonStringTrial));
yield return webRequest.SendWebRequest();
Debug.Log(jsonStringTrial);
Debug.Log("This was not Working");
Debug.Log("Data we Received : " + webRequest.downloadHandler.text); // this is always emtpy in webgl but works in editor
if(webRequest.result == UnityWebRequest.Result.ProtocolError)
{
Debug.Log(webRequest.result);
Debug.Log("Protocol Error");
Debug.Log(webRequest.error);
Debug.Log("Error Code" + webRequest.responseCode);
}
if (webRequest.result == UnityWebRequest.Result.DataProcessingError)
{
Debug.Log(webRequest.result);
Debug.Log("DataProcessingError");
Debug.Log(webRequest.error);
Debug.Log("Error Code" + webRequest.responseCode);
}
if (webRequest.result == UnityWebRequest.Result.ConnectionError)
{
Debug.Log(webRequest.result);
Debug.Log(webRequest.error);
Debug.Log("ConnectionError");
Debug.Log("Error Code" + webRequest.responseCode);
}
if (webRequest.result == UnityWebRequest.Result.Success)
{
Debug.Log(webRequest.result);
Debug.Log("Error Code" + webRequest.responseCode);
}
if (webRequest.downloadHandler.text == "{}" || string.IsNullOrEmpty(webRequest.downloadHandler.text))
{
MainMenuHandler.Instance.OpenPanel(MainMenuHandler.Instance.playerLoginPanel);
StartCoroutine(nameof(DisplayMessage));
messageField.text = "Creating Player";
}
else
{
var newData = JsonConvert.DeserializeObject<Root>(webRequest.downloadHandler.text);
PlayerPrefs.SetString(playerNamePrefKey, newData.Item.name);
PlayerPrefs.SetInt("PlayerAvatar", newData.Item.character);
StartCoroutine(GetUserBalance());
yield return new WaitForSeconds(2f);
//NetworkManager.Instance.Connect();
StartCoroutine(nameof(DisplayMessage));
messageField.text = "Getting Data";
}
}
}
Browser Console Log
The "correct" way to fix this issue is to have a look why the server is returnig a 500 Error. 500 errors mean that the problem is something on the server and not on the (Unity-)Client.
So it's not really a Unity problem but a Server problem.

SqlDataReader is lost after posting request using RestSharp

I'm writing a Windows service. It periodically connects to a SQL database and looks for new records. I can read the SQL database without an issue and it gets the data using a SqlDataReader. I then have a while loop that just does a while Read. Part way through the while loop I create a web request to send that data to a server side component. For that I am using RestSharp v107. When I call ExecuteAsync with the request, I can see the data being sent and it ends up on my server side without an issue. However, when the response comes back, it has wiped out my SqlDataReader so on the next loop I get "Exception: Invalid attempt to call Read when reader is closed." as the reader is null. Here is the code, truncated where necessary for brevity.
private async Task AddUpdateCustomers(SqlConnection poConn)
{
string sQuery = "select * from customers";
try
{
SqlCommand oCmd = new SqlCommand(sQuery, poConn);
poConn.Open();
using (SqlDataReader dataReader = oCmd.ExecuteReader())
{
if (dataReader.HasRows)
{
while (dataReader.Read())
{
int iRecordId = dataReader.GetInt32(dataReader.GetOrdinal("ID"));
Customer customer = new Customer()
{
CustomerId = dataReader.GetString(dataReader.GetOrdinal("CustomerCodeFinancialReference")),
Name = dataReader.GetString(dataReader.GetOrdinal("Name"))
// more fields here removed for brevity
};
RestRequest request = new RestRequest();
request.AddHeader("Profile", aCLIntacctClientServiceConfiguration.ProfileName);
request.AddHeader("Entity", aCLIntacctClientServiceConfiguration.EntityName);
request.AddHeader("CreateUpdate", dataReader.GetBoolean(dataReader.GetOrdinal("IsNew")) ? "create" : "update");
request.AddHeader("Type", "Customer");
request.AddHeader("CorrelationId", Guid.NewGuid().ToString());
string body = ObjectToString(customer);
request.AddStringBody(body, DataFormat.Json);
var options = new RestClientOptions(ClientURI)
{
ThrowOnAnyError = false,
Timeout = 30000
};
RestClient client = new RestClient(options);
RestResponse response = await client.ExecuteAsync(request);
if (!string.IsNullOrEmpty(response.Content))
{
try
{
CustomResponse customerResponseObject = JsonConvert.DeserializeObject<CustomResponse>(response.Content);
if (customerResponseObject.ExitCode == 0)
{
WriteBackToStagingTable(iRecordId, true, "");
}
else
{
string sMessages = "";
foreach (CustomResponseMessage message in customerResponseObject.Messages)
{
sMessages += $"Record ID '{message.RecordId}' failed with the following error: '{message.MessageValue}'" + Environment.NewLine;
}
WriteBackToStagingTable(iRecordId, false, sMessages);
}
}
catch (Exception ex)
{
WriteBackToStagingTable(iRecordId, false, ex.Message + Environment.NewLine + response.Content);
}
}
}
if (!dataReader.IsClosed)
{
dataReader.Close();
}
}
else
{
// No records read from db
}
}
}
catch (Exception ex)
{
HandleLogRequest("Exception: " + ex.Message);
}
}
I've tried using PostAsync but that didn't work and reading the documentation, it isn't what I want. I cannot see why after calling client.ExecuteAsync the dataReader is suddenly null. I'm using RestSharp v107 and so many examples on the web but they are earlier versions and there are a lot of differences.
Rather than pass the connection round as it wasn't particularly necessary, I moved the connection into each function and created it as necessary. With the SQL data reader, I didn't bother with the using block. I also changed it so that it was executing asynchronously.
SqlDataReader dataReader = await oCmd.ExecuteReaderAsync();
Once I'd done that, calling the rest client execute method, it returned and the data reader was still in scope.

A possible object cycle was detected. in both System.Text.Json and Newtonsoft.Json

I have been pulling my hair out with this one.
I have a very simple test class that throws this error:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
It doesn't seem to break much, as the put request is successful and the serialize is also successful.
EDIT
I have chased the serialize exception out if it was ever really there. I am starting to think it is a problem with typed HttpClient. It throws the exception that comes out on the console and in the response on Postman. However, it doesn't allow me to catch the exception in the code and the PUT call works. So the exception is happening after the PUT request and is handled before it returns control to my app.
I am going to try to use a standard HttpClientFactor instead of a typed client and see if that works. I know that the JSON exception is a red herring, but it is ugly and breaking the response.
Any suggestions would be welcome.
public virtual async Task<CouchResponse> Create(string id, string db, TObj info)
{
CouchResponse ret = new() { Reason = "Unknown and unExpected error", Ok = false };
HttpResponseMessage rc = null;
if (id is null)
{
return new CouchResponse() { Id = "missing", Ok = false, Rev = "missing" };
}
string url = $"{db}/1";
try
{
// login to Couchdb servwer
await CouchLogin();
try
{
//var jsonInfo = JsonUtils.Serialize<TestJson>(jTest);
var jsonInfo = JsonSerializer.Serialize<TObj>(info, options);
HttpContent content = new StringContent(jsonInfo, Encoding.UTF8,
"application/json");
rc = await client.PutAsync(url, content);
}
catch (Exception eNewton)
{
Console.WriteLine($"Json Exception: {eNewton.Message}");
}
if (rc is not null)
{
var str = await rc.Content.ReadAsStringAsync();
var ret = JsonSerializer.Deserialize<CouchResponse>(str,options);
rc.EnsureSuccessStatusCode();
}
return ret;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//return ret;
}
return ret;
}
Suggestions?
What a crazy bug. The diagnostic was very missing leading. Everything I was doing in the create method was correct.
What is missed was an await when I called the create method. This made it appear that the sendAsync was having the issue when it was really the controller trying to format the task return as a response. This caused the stack trace in the response message. Thanks for all the help.
Change this
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
To this
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
MaxDepth = null,
};

Flurl Post Not Returning from Web Api

I've got a Xamarin application using Flurl, with the following post to a Web Api
Xamarin App:
private async Task<LoginResponse> processLogin()
{
try
{
return await "http://192.168.0.12:60257/api/loginapi/Login".WithTimeout(10).PostJsonAsync(new { username = "fsdafsd", password = "gdfgdsf" }).ReceiveJson<LoginResponse>();
}
catch (Exception e)
{
return new LoginResponse { ResponseStatusCode = -1 };
}
}
Web Api:
public LoginResponse Login([FromBody]LoginRequest loginRequest)
{
var result = new LoginResponse();
try
{
var user = this.UserManager.FindAsync(loginRequest.username, loginRequest.password);
if (user != null)
{
result.ResponseStatusCode = 1;
}
else
{
result.ResponseStatusCode = 0;
}
}
catch (Exception e)
{
result.ResponseStatusCode = -1;
}
return result;
}
I can see my Web Api method getting hit, and it returns the expected object type, not my Xamarin application continues to wait on the Flurl Post.
Can anyone advise what I might be doing wrong?
UPDATE:
I have noticed that the following does work, but it's not ideal:
dynamic result = await "http://192.168.0.12:60257/api/loginapi/Login".PostJsonAsync(new { username = "fsdafsd", password = "gdfgdsf" }).ReceiveJson();
Fixed it. For whatever reason, it was the type I was trying to return. Changing the object variable type to "dynamic" fixed this, and allowed me to deserialise the object correctly.
dynamic result = await "http://192.168.0.12:60257/api/loginapi/Login".PostJsonAsync(new { username = "fsdafsd", password = "gdfgdsf" }).ReceiveJson();
Returns a dynamic object with the properties I'd expect in the normal structure.
If anyone can enlighten my why I couldn't do:
LoginRequest result = ...
It'd be appreciated.

Cannot use SendTweetWithMediaOptions in windows phone

I am using TweetSharp in a Windows Phone project and no matter what I do, I can't post a tweet with media.
I am getting the exception 195: Missing or invalid parameter.
I read that usually this can be a cause of invalid data, like the stream that I provide is invalid.
I have tried other way but nothing works , I get the same exception ...
The sharing code, simplified is like this:
MediaLibrary library = new MediaLibrary();
var picture = library.Pictures[0];
var options = new SendTweetWithMediaOptions
{
Images = new Dictionary<string, Stream> { { picture.Name, picture.GetImage() } },
Status = TweetTextBox.Text,
};
AutentificateTwitterService().SendTweetWithMedia(options, (status, response) =>
_dispatcher.BeginInvoke(() =>
{
DonePosting();
if (response.StatusCode == HttpStatusCode.OK)
{
_lastPostId = status.Id;
}
else
{
MessageBox.Show(String.Format(
"There was an error sending image to Twitter{0}{1}",
Environment.NewLine,
response.Error));
}
}));
I tried sharing with linqtotwitter and worked but TweetSharp is more appropriate for my project.
Finally after some time I've found the problem to this and I am sure to other more WP and SendTweetWithMediaOptions related problems.
The thing is that if you dig into SendTweetWithMedia the way it is now you will get to TwitterService.cs where WithHammock will be called, is just the images are not passed as parrameters, so they get lost right there :)
I did fix this passing the parameters and adding
private void WithHammock<T>(WebMethod method, Action<T, TwitterResponse> action, string path, IDictionary<string, Stream> files, params object[] segments) where T : class
{
var url = ResolveUrlSegments(path, segments.ToList());
var request = PrepareHammockQuery(url);
request.Method = method;
request.QueryHandling = QueryHandling.AppendToParameters;
foreach (var file in files)
{
request.AddFile("media[]", file.Key, file.Value);
}
WithHammockImpl(request, action);
}
I will try and see if I can Pull this so that everyone else can have this fix.
Hope this helps.