Same GET request to same URL give different Response, strange behavior - rest

I have a very strange bug and I don't know what is going on.
I have an endpoints like this:
private void init() {
if (ioConfigurationDAO == null) {
ioConfigurationDAO = new IOConfigurationDAO();
ioConfigurationDAO.init();
}
property = new AigatewayProperty();
}
#GET
#Path("/{id : \\d+}")
#Produces(MediaType.APPLICATION_JSON)
public Response getIoConfiguration(#PathParam("id") Integer id) {
init();
if (!ChannelName.isValidChannel(id)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
IOConfiguration ioConfig = ioConfigurationDAO.findIOConfiguration("CH" + id);
System.out.println(ioConfig.getConversionType());
// close();
return Response.status(Response.Status.OK).entity(ioConfig).build();
}
When I am making request to this url: http://localhost:8080/aigateway/rest/ioconfiguration/3
Some time, I get a correct response:
{"ioConfigurationId":"CH3","active":true,"name":"1","conversionType":"Linear","mInfo":0.32,"bInfo":0.55,"voltageDivide":"/4","sampleRange":"24
Bits","samplePeriod":10,"storeRaw":false,"storeConverted":false,"defaultGraph":"Line","title":"","unit":"","rangeLowerbound":0,"rangeUpperbound":100,"code":"function
conversion_CH3 (input) {\n\treturn input;\n}"}
Sometimes, I get wrong response with null values:
{"ioConfigurationId":"CH3","active":null,"name":null,"conversionType":null,"mInfo":null,"bInfo":null,"voltageDivide":null,"sampleRange":null,"samplePeriod":null,"storeRaw":null,"storeConverted":null,"defaultGraph":null,"title":null,"unit":null,"rangeLowerbound":null,"rangeUpperbound":null,"code":null}
I don't know what is going on.
One thing to mention is that:
I have to manually initiate my entity manager becuase my EJB annotations doesn't work, and I am not closing my connection to the database since I don't know when the applicaton will end. I don't know if this is the reason that cause this problem.
Someone please help me, if you need more information, I am willing to share.
Thanks!

I solved this problem by using EJB properly. The only reason I can think that is causing this problem is because I never close the my entity manager, so the next time when I am trying to create a new one, there is some problem going on and that's why I am getting null values sometimes.

Related

EF Core IgnoreQueryFilters behavior on multiple subsequent queries

i've a problem with the IgnoreQueryFilters.
I've implemented soft-delete using the HasQueryFilter ( in the OnModelCreating i apply the global query filter to every entity which implements a particular interface ).
The problem is that if i launch a query 2 times in the same request:
the first time asking for also the "IsDeleted = true" entities ( so including IgnoreQueryFilters ),
and the second time asking only for the "IsDeleted = false" ( so not including the IgnoreQueryFilters)
the second time i still get also the "deleted" entities.
I think that this happens because when i launch the query for the second time, the entities are already in the context and i get them instead of the right results.
Here how i build the method for "including / excluding" the deleted entities.
// this is my repo pattern implementation
public class MyEntityRepo()
{
....
public Task<List<MyEntity>> GetEntityByUserId(int userId, bool ignoreQueryFilter = false)
{
var query = context.blabla
.Include(c => c.blabla2)
.Where(c => c.ApplicationUserId == userId);
if (ignoreQueryFilter)
{
query = query.IgnoreQueryFilters();
}
var result = await query.ToListAsync();
return result;
}
}
Now if in a service i call it this way:
public void MyServiceMethod()
{
...
var IncludeDeleted = await myEntityRepo.GetEntityByUserId(1, true);
//Here i need to do a sync with other data and for this reason i need also the deleted entities
foreach( var e in includeDeleted)
{
// do something
}
await context.SaveChangesAsync();
//Now that my data is correctly synced i've to get the data again but this time excluding the deleted entities
// and it fails
var ExcludeDeleted = await myEntityRepo.GetEntityByUserId(1, false);
return ExcludeDeleted;
}
The only way i found to solve the problem is to do something like context.ChangeTracker.Clear() before the second call to myEntityRepo.GetEntityByUserId, but is this the right way to go?
Since in real the method is a little bit more complex and can be re-used in other areas, i'm not sure that calling a Clear is a good idea because tomorrow it might be called in a bigger method and cause unexpected problems.
What's the best practice to use when i need to get data with and without query filter?
Is it ok to clear the change tracker?
If yes, what's the best time to clear it? in the GetEntityByUserId if i just ignoredTheFilters ( for consistency ) or after, in the caller method, whenever i find a problem like this one?
Actually i've also thinked about removing the GlobalQueryFilter usage and replace it with methods in the repos that get or exclude deleted entities... yes i've to remember to always filter out but feels more practical.

Asp.Net Web API Error: The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'

Simplest example of this, I get a collection and try to output it via Web API:
// GET api/items
public IEnumerable<Item> Get()
{
return MyContext.Items.ToList();
}
And I get the error:
Object of type
'System.Data.Objects.ObjectQuery`1[Dcip.Ams.BO.EquipmentWarranty]'
cannot be converted to type
'System.Data.Entity.DbSet`1[Dcip.Ams.BO.EquipmentWarranty]'
This is a pretty common error to do with the new proxies, and I know that I can fix it by setting:
MyContext.Configuration.ProxyCreationEnabled = false;
But that defeats the purpose of a lot of what I am trying to do. Is there a better way?
I would suggest Disable Proxy Creation only in the place where you don't need or is causing you trouble. You don't have to disable it globally you can just disable the current DB context via code...
[HttpGet]
[WithDbContextApi]
public HttpResponseMessage Get(int take = 10, int skip = 0)
{
CurrentDbContext.Configuration.ProxyCreationEnabled = false;
var lista = CurrentDbContext.PaymentTypes
.OrderByDescending(x => x.Id)
.Skip(skip)
.Take(take)
.ToList();
var count = CurrentDbContext.PaymentTypes.Count();
return Request.CreateResponse(HttpStatusCode.OK, new { PaymentTypes = lista, TotalCount = count });
}
Here I only disabled the ProxyCreation in this method, because for every request there is a new DBContext created and therefore I only disabled the ProxyCreation for this case .
Hope it helps
if you have navigation properties and you do not want make them non virtual, you should using JSON.NET and change configuration in App_Start to using JSON not XML!
after install JSON.NET From NuGet, insert this code in WebApiConfig.cs in Register method
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
If you have navigation properties make them non virtual. Mapping will still work but it prevents the creation of Dynamic Proxy entities which cannot be serialized.]
Not having lazy loading is fine in a WebApi as you don't have a persistent connection and you ran a .ToList() anyway.
I just disabled proxy classes on a per needed basis:
// GET: ALL Employee
public IEnumerable<DimEmployee> Get()
{
using (AdventureWorks_MBDEV_DW2008Entities entities = new AdventureWorks_MBDEV_DW2008Entities())
{
entities.Configuration.ProxyCreationEnabled = false;
return entities.DimEmployees.ToList();
}
}
Add the following code in Application_Start function of Global.asax.cs:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
This instruct the API to serialize every response into JSON and remove XML responses.
In my case the object being returned had a property within it with a type that did not have an argumentless/default constructor. By adding a zero-argument constructor to that type the object could be serialized successfully.
I had the same problem and my DTO was missing an parameter less constructor.
public UserVM() { }
public UserVM(User U)
{
LoginId = U.LoginId;
GroupName = U.GroupName;
}
First constructor was missing.
I got this error message and it turns out the problem was that I had accidentally set my class to use the same serialized property name for two properties:
public class ResultDto
{
//...
[JsonProperty(PropertyName="DataCheckedBy")]
public string ActualAssociations { get; set; }
[JsonProperty(PropertyName="DataCheckedBy")]
public string ExpectedAssociations { get; set; }
//...
}
If you're getting this error and you aren't sending entities directly through your API, copy the class that's failing to serialize to LINQPad and just call JsonConvert.SerializeObject() on it and it should give you a better error message than this crap. As soon as I tried this it gave me the following error message: A member with the name 'DataCheckedBy' already exists on 'UserQuery+ResultDto'. Use the JsonPropertyAttribute to specify another name.
After disable Proxy Creation, use eager loading (Include()) to load the proxy object.
In my Project EntityCollection returned from the WebApi action method.
Configuration.ProxyCreationEnabled = false not applicable. I have tried the below approach it is working fine for me.
Control Panel.
2.Turn on Windows Features on or off
Choose Internet Information Service
Check all the World Wide Web Components it would be better to check all the components in IIS.
Install the components.
Go to (IIS) type inetmgr in command prompt.
select the published code in the Virtual directory.
Convert into application
Browse it the application.
The answer by #Mahdi perfectly fixes the issue for me, however what I noticed is that if my Newtonsoft.JSON is 11.0 version then it doesn't fix the issue, but the moment I update Newtonsoft.JSON to latest 13.0 it starts working.

REST PUT method seems to work but doesn't edit an entity

I have a REST Web Service API. I mapped database using JPA. I have an entity "persona". Adding a new entity with POST method works fine, also GET method works fine, but when I try to call PUT method, there is some exception that I found out while debugging: "Cannot suppress a null exception." and "Self-suppression not permitted". In the test database with other entities everything works fine...
Adding works almost the same like editing in my case - firstly I only get the values and then after changing I do everything the same, the only difference is that there is used method PUT instead of POST.
This is my PUT method (here the exception occurs):
#PUT
#Consumes({"application/xml", "application/json"})
public Response edit(Persona entity) {
try {
getJpaController().edit(entity);
return Response.ok().build();
} catch (Exception ex) {
return Response.notModified(ex.getMessage()).build();
}
}
I'm working first time with web services, so I'm a newbie.
What can be the reason of such behaviour? What is this self-suppression error?
If you need any source code else, please, tell me, I will edit my post.
#EDIT:
I found some exception in JpaController Class, my Persona class has:
#OneToOne(cascade = CascadeType.ALL, mappedBy = "persona")
private Personaacceso personaacceso;
In JpaController there is:
Personaacceso personaaccesoOld = persistentPersona.getPersonaacceso();
Personaacceso personaaccesoNew = persona.getPersonaacceso();
if (personaaccesoOld != null && !personaaccesoOld.equals(personaaccesoNew)) {
if (illegalOrphanMessages == null) {
illegalOrphanMessages = new ArrayList<String>();
}
illegalOrphanMessages.add("You must retain Personaacceso " + personaaccesoOld + " since its persona field is not nullable.");
}
So there is showing a message that I have to retain Personaacceso. Any idea how to solve it?
Okey, I know what was the reason now...
Each Persona entity has some other entities (one-to-one or one-to-many). The Jpa Controller wasn't retaining all these containing entities (instead, it was creating new ones). So, the data was lost and because of that persona entity wasn't edited.
Solution:
To every containing entity do something like:
containedEntityNew=containedEntityOld;
However, take into consideration, that then these entity-fields are just rewrited from the old "main" entity.

Silverlight 4 Entity framework issue

I have created a sample application in Silverlight with RIA services. I am using entity framework for CRUD operation but it does not work for INSERT Operation with following Exception, "Submit operation failed validation. Please inspect Entity.ValidationErrors for each entity in EntitiesInError for more information." I have not apply any validation but don't know how the error occurs.
I have tested that when I create an object of DB entity and assign values to it and then save by calling object.SaveChages(), it works fine. But its default method does not work. Any help is appreciated.
Thanks
The SubmitOperation callback has an EntitiesInError property which you can use to iterate thru the entities. That's the way of getting the "real" error.
Here's the method I have to show the user what went wrong...
public static bool WasSubmittedOK(SubmitOperation so, string errorMessageHeader, out string errorMessage)
{
errorMessage = string.Empty;
if (!so.HasError)
return true;
so.MarkErrorAsHandled();
errorMessage = "An unknown error has occurred";
if (so.EntitiesInError.Count() > 0)
{
StringBuilder builder = new StringBuilder();
builder.AppendFormat("{0}\r\n", errorMessageHeader);
foreach (Entity item in so.EntitiesInError)
{
#if DEBUG
builder.AppendFormat("\r\nFor {0}", item.GetType());
#endif
foreach (ValidationResult error in item.ValidationErrors)
{
builder.AppendFormat("\r\n- {0}", error.ErrorMessage);
Debug.WriteLine(string.Format("Error in {0}:'{1}'", string.Join(",", error.MemberNames.ToArray()), error.ErrorMessage));
}
}
errorMessage = builder.ToString();
}
else if (so.Error != null) { errorMessage = so.Error.Message; }
return false;
}
Are you able to drill into the validation errors? I actually have an article about this coming in December MSDN Magazine Data Points but I bet you don't want to wait, right? :)
Even if you haven't applied any specific validations, there are things like foreign key contsraints that EF will still check. If you can see what the error is that will be ultimately useful in solving your problem. Debug into the exception. See if there is a DbEntityValidationException available...maybe it's in an innerexceptoin. DbEntityValidationException will have one or more EntityValidationErrors. Each of those contains a list of all of the errors found for one instance. That means expanding the EntityValidationErrors items one at a time and looking at the ValidationError items contained within.

The given key was not present in the dictionary

I am trying to make a simple plugin for MS Dynamics CRM 4.0 where send data of a salesorder in a SOAP message on the update of the order.
The strange thing is that I get this error every other time i try to save /(execute the plugin).
So when I update (any field) of a salesorder and then save I get the error:
The given key was not present in the dictionary.
When I save again right away after that(without even changing anything in between the two saves) it executes correctly and gives me all data I want. It is really every time the same thing: first save: error, second save: execute correctly.
Any ideas what this could be?
This is the first part of my code; where it actually gets the dataset of the salesorder in this case:
public class CompleteOrderPlugin : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
DynamicEntity entity = null;
if (context.InputParameters.Properties.Contains(ParameterName.Target) &&
context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)
{
entity = (DynamicEntity)context.InputParameters[ParameterName.Target];
if (entity.Name != EntityName.salesorder.ToString()) { return; }
}
else
{
return;
}
The rest is where I use values from attributes to fill my own variables.
I fixed this by first making a Post Image of the salesorder in the plugin regsitration tool and then using the values in the Post Image instead of the ones comming directly from the salesorder. This I did because on a update you get only the values that actually changed.