I am getting an error in this line of code Session.Linq<Employees>() :
" An object reference is required for non-static field,method, or property 'System.Web.UI.Page.Session.get'.
This is my code :
public static object GetData(Dictionary<string, object> tableParams)
{
IQueryable<Employees> Employee = Session.Linq<Employees>();
if (tableParams.ContainsKey("sEcho"))
{
var parser = new DataTableParser<Employees>(tableParams, Employee);
return parser.Parse();
}
return Employee;
}
If I use HttpContext.Current.Session.Linq<Employees>();
then i get:
'System.Web.SessionState.HttpSessionState' does not contain a definition for 'Linq' and no extension method 'Linq' accepting a first argument of type 'System.Web.SessionState.HttpSessionState' could be found '
What do i need to do to get this to work? Am I missing a namespace for Linq with regard to Session?I am using System.Linq and System.Linq.Expression.
I think you're misunderstanding something. What you're trying to do doesn't have anything to do with Linq, at least not in the context of retrieving the object from session.
You need to retrieve the object from session and unbox it:
var list = Session["MyList"] as List<int>;
if (list != null)
{
//the list was found and you can start using it here
}
Related
In the following code, I serialize an object using Json.Net. This Json has type names embedded. I then change one of the type names to induce an error (this is a test, I am dealing with a real issue in an existing project). When I deserialize the Json, I expect to get an object back that has a null value for the property with the fiddled type name. Instead the serializer craps out and returns null. Are my expectations correct? Can I change the settings somehow so that I will get a non-null object for my root object? Note that the second error that I get suggests that there is a bug in the serializer.
static public class JsonTest
{
static public void Test()
{
// Create test object
A a = new A
{
MyTest = new MyTest(),
};
// Serialize it.
string json = JsonConvert.SerializeObject(a, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
// Fiddle class name to induce error
json = json.Replace("+MyTest", "+MyTest2");
// Before: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest, <Assembly>"}}
// After: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest2, <Assembly>"}}
// Deserialize
A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Error = (object sender, ErrorEventArgs e) =>
{
e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type
}
});
// A second error occurs: Error = {Newtonsoft.Json.JsonSerializationException: Additional text found in JSON string after finishing deserializing object....
// a2 is null
}
public class A
{
public ITest MyTest { get; set; }
}
public interface ITest { }
public class MyTest : ITest { }
}
Update
This issue has been fixed in Json.NET 10.0.2 in this submission.
Original Answer
This looks to be a bug in Json.NET. If I set JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead then the problem goes away:
// Deserialize
A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead,
Error = (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e) =>
{
Debug.WriteLine(e.ErrorContext.Path);
e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type
}
});
Debug.Assert(a2 != null); // No assert.
However, it should not be necessary to turn on this setting, which enables reading metadata properties including "$type" located anywhere in a JSON object, rather than just as the first property. Most likely it coincidentally fixes the bug since it requires pre-loading the entire JSON object before beginning deserialization.
You could report an issue if you want.
Debugging a bit, the problem seems to be that, because the inner MyTest object cannot be constructed, the exception is caught and handled by JsonSerializerInternalReader.PopulateObject() while populating the outer object A. Because of this, the JsonReader does not get advanced past the inner, nested object, leaving the reader and serializer in an inconsistent state. This accounts for the second exception and the eventual Additional text found in JSON string after finishing deserializing object. Path '' exception.
I have a problem with an XML response to a call to the Web API.
Specifically, I have a function "GetValue" call that when I should return in XML format based to the id or class "Cellulare" or class "Televisore".
The problem is that if I make a request from browser gives me the following error:
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
This is the example:
Public Class Cellulare
Public Property Colore As String
Public Property SistemaOperativo As String
End Class
Public Class Televisore
Public Property Colore As String
Public Property Marca As String
End Class
Public Function GetValue(ByVal id As Integer) // ' As Cellulare
If Id = 1 Then
Dim MyTelevisore As New Televisore
MyTelevisore.Colore = "grigio"
MyTelevisore.Marca = "lg"
Return MyTelevisore
Else
Dim MyCellulare As New Cellulare
MyCellulare.Colore = "nero"
MyCellulare.SistemaOperativo = "android"
Return MyCellulare
End If
End Function
Can anyone help me to solve this problem???
Thank in advance
greetings
Donato
I think your approach is wrong.
You have simple objects to return, that can be handled easily by the default serializers webapi has to offer.
Your returned object type should be IHttpActionResult (webapi2) or HttpResponseMessage.
I would NOT go for what #Frank Witte suggested, cause returning the object itself is bad practice. Specifically here you can just return a generic object through IHttpActionResult / HttpResponseMessage.
You should do something like:
Public Function GetValue(ByVal id As Integer) As IHttpActionResult
If Id = 1 Then
Dim MyTelevisore As New Televisore
MyTelevisore.Colore = "grigio"
MyTelevisore.Marca = "lg"
Return Ok(MyTelevisore)
Else
Dim MyCellulare As New Cellulare
MyCellulare.Colore = "nero"
MyCellulare.SistemaOperativo = "android"
Return Ok(MyCellulare)
End If
End Function
It throws the error because you do not supply any return type to your GetValue function. You commented that out.
As I can tell from your code you are returning a different type of object depending on the id you supply to the GetValue call. I do not know the complete context of what you are trying to do, but from what I can see it would make more sense to have a different controller, or route at least, for the different types of object:
/api/cellulare/<id>
Would map to a controller CellulareController.
/api/televisore/<id>
Would map to a controller TelevisoreController. Each with their own Get(), Post() and Delete() methods if you will.
Hope this helps.
As I read explanation here, I found that Spring can automatically bind GET request parameter to a type. Below is the sample code from the link.
#Controller
#RequestMapping("/person")
public class PersonController {
...
#RequestMapping("/create")
public String create(Person p) {
//TODO: add Person to DAO
return "person/show";
}
}
Can someone tell me how spring do this? What bean that contains the logic to convert the parameter onto command type (Person type)?
The trick is done here: org.springframework.web.method.annotation.ModelAttributeMethodProcessor#resolveArgument()
This is the excerpt of code where it actually binds the class to the values:
String name = ModelFactory.getNameForParameter(parameter);
//Here it determines the type of the parameter and creates an instance
Object attribute = (mavContainer.containsAttribute(name)) ?
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request);
//Then it binds the parameters from the servlet to the previously created instance
WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
if (binder.getTarget() != null) {
bindRequestParameters(binder, request);
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors()) {
if (isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
}
I'm using Entity Framework Code First table-per-hierarchy in my ASP.NET Web API project. One of my models has a List that is of the type of the abstract base class of the hierarchy.
List<Dog> // (for example; with GoldenRetriever, BorderCollie, etc inheriting)
I'm trying to test POSTing some data to my API Controller using Fiddler. But I don't know how to represent the JSON when I do so. If I try something like:
"Dogs":
[
{"Name":"Bud", "Age":"3"}
]
I get the error:
"Could not create an instance of type Models.Dog. Type is an interface
or abstract class and cannot be instantiated."
Specifying the Discriminator in the JSON doesn't help me either. Anyone have any ideas? Thanks!
Edit: Solution
The trick is to use the $type property in the JSON string. For more information see this link suggested by m.t.bennett in the comments.
To enable using the $type property I needed to add the following to WebApiConfig.cs:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling
= TypeNameHandling.Auto;
Then when posting the JSON to Fiddler, I added the $type property with the full object path:
{"$type":"Example.Models.Dogs.GoldenRetriever, Example.Models",
"Name":"Bud","Age":3}
For me to figure out this formatting I used Snixtor's suggestion to serialize an object and output the JSON string. Brilliant!
I'm not sure if this is the most elegant solution since it's JSON.NET specific, but it works!
I used a custom JsonConverter to handle the base-type deserialization.
public override bool CanConvert(Type objectType) {
return typeof(Mybase).Equals(objectType);
}
public override MyBase Deserialize(JsonReader reader, MyBase existingValue, JsonSerializer serializer) {
var ret = existingValue;
var jobj = JObject.ReadFrom(reader);
if (jobj["type"] == null || jobj["type"].Type != JTokenType.String)
throw new JsonSerializationException("Supplied JSON is missing the required 'type' member.");
var typeName = jobj["type"].Value<string>();
var t = this.GetType().Assembly.GetType("MyNamespace." + typeName);
if(t == null)
throw new JsonSerializationException(String.Format("Could not identify supplied type '{0}' as a known type.", typeName));
if (existingValue != null && !t.IsInstanceOfType(existingValue))
throw new JsonSerializationException(String.Format("Type Mismatch: existingValue {0} is not assignable from supplied Type {1}", existingValue.GetType().Name, t.Name));
ret = (ContactMethod)jobj.ToObject(t);
return ret;
}
And registered the JsonConverter durring application initialization:
JsonSerializerSettings settings;
settings.Converters.Add(new MyBaseConverter());
I have an object I want to update in the database. I'm new to EF but have done a fair bit of reading. Clearly my approach is wrong, but I don't understand why. FYI the Context referenced throughout is an ObjectContext which is newly instantiated as this code begins and is disposed immediately after. Here is my Update method - the View is the object I want to update in the database and it has 4 ICollection properties whose changes I also wish to save to the database:
public void Update(View view)
{
var original = Read(view.Username, view.ViewId);
original.ViewName = view.ViewName;
ProcessChanges<CostCentre, short>(Context.CostCentres, original.CostCentres, view.CostCentres, "iFinanceEntities.CostCentres", "CostCentreId");
ProcessChanges<LedgerGroup, byte>(Context.LedgerGroups, original.LedgerGroups, view.LedgerGroups, "iFinanceEntities.LedgerGroups", "LedgerGroupId");
ProcessChanges<Division, byte>(Context.Divisions, original.Divisions, view.Divisions, "iFinanceEntities.Divisions", "DivisionId");
ProcessChanges<AnalysisCode, short>(Context.AnalysisCodes, original.AnalysisCodes, view.AnalysisCodes, "iFinanceEntities.AnalysisCodes", "AnalysisCodeId");
int test = Context.SaveChanges();
}
First I get the original from the database because I want to compare its collections with the new set of collections. This should ensure the correct sub-objects are added and removed. I compare each collection in turn using this ProcessChanges method:
private void ProcessChanges<TEntity, TKey>(ObjectSet<TEntity> contextObjects, ICollection<TEntity> originalCollection, ICollection<TEntity> changedCollection, string entitySetName, string pkColumnName)
where TEntity : class, ILookupEntity<TKey>
{
List<TKey> toAdd = changedCollection
.Select(c => c.LookupKey)
.Except(originalCollection.Select(o => o.LookupKey))
.ToList();
List<TKey> toRemove = originalCollection
.Select(o => o.LookupKey)
.Except(changedCollection.Select(c => c.LookupKey))
.ToList();
toAdd.ForEach(a =>
{
var o = changedCollection.Single(c => c.LookupKey.Equals(a));
AttachToOrGet<TEntity, TKey>(entitySetName, pkColumnName, ref o);
originalCollection.Add(o);
});
toRemove.ForEach(r =>
{
var o = originalCollection.Single(c => c.LookupKey.Equals(r));
originalCollection.Remove(o);
});
}
This compares the new collection to the old one and works out which objects to add and which to remove. Note that the collections all contain objects which implement ILookupEntity.
My problems occur on the line where I call AttachToOrGet. This method I got from elsewhere on stackoverflow. I'm using this because I was often getting a message saying that "An object with the same key already exists in the ObjectStateManager" when attaching a new subobject. Hopefully you'll understand my confusion around this when I post the code of this method below:
public void AttachToOrGet<TEntity, TKey>(string entitySetName, string pkColumnName, ref TEntity entity)
where TEntity : class, ILookupEntity<TKey>
{
ObjectStateEntry entry;
// Track whether we need to perform an attach
bool attach = false;
if (Context.ObjectStateManager.TryGetObjectStateEntry(new EntityKey(entitySetName, pkColumnName, entity.LookupKey), out entry))
//if (Context.ObjectStateManager.TryGetObjectStateEntry(Context.CreateEntityKey(entitySetName, entity), out entry))
{
// Re-attach if necessary
attach = entry.State == EntityState.Detached;
// Get the discovered entity to the ref
entity = (TEntity)entry.Entity;
}
else
{
// Attach for the first time
attach = true;
}
if (attach)
Context.AttachTo(entitySetName, entity);
}
Basically this is saying if the entity is not already attached then attach it. But my code is returning false on the Context.ObjectStateManager.TryGetObjectStateEntry line, but throwing an exception on the final line with the message "An object with the same key already exists in the ObjectStateManager". To me this is paradoxical.
As far as I'm concerned I'm trying to achieve something very simple. Something it would take 20 minutes to write a stored procedure for. A simple database update. Frankly I don't care what is attached and what isn't because I don't wish to track changes or create proxies or lazy load or do anything else EF offers me. I just want to take a very simple object and update the database using a minimal number of trips between servers. How is this so complicated? Please someone help me - I've spent a whole day on this!
Update
Here's my ILookupEntity class:
public interface ILookupEntity<TKey>
{
TKey LookupKey { get; }
string DisplayText { get; }
}
Here's how it is implemented in CostCentre:
public partial class CostCentre : IFinancialCode, ILookupEntity<short>
{
#region IFinancialCode Members
public short ID { get { return CostCentreId; } }
public string DisplayText { get { return string.Format("{0} - {1}", Code, Description); } }
#endregion
#region ILookupEntity Members
public short LookupKey
{
get { return ID; }
}
#endregion ILookupEntity Members
}
Well, I've worked through this and found a solution, but I can't say I understand it. The crucial ingredient came when I was performing a check after the comment by #Slauma. I wanted to check I was using the correct entity set name etc so I included the following lines near the top of my AttachToOrGet method:
var key = new EntityKey(entitySetName, pkColumnName, entity.LookupKey);
object temp;
if (!Context.TryGetObjectByKey(key, out temp))
throw new Exception(string.Format("No entity was found in {0} with key {1}", entitySetName, entity.LookupKey));
Bizarrely this alone resolved the problem. For some reason, once I'd called the TryGetObjectByKey then the ObjectStateManager.TryGetObjectStateEntry call actually started locating the attached entity. Miraculous. I'd love it if anyone can explain this.
By the way, I also needed to include the following code, but that's just because in my case the modelled entities are located in a separate assembly from the context itself.
Assembly assembly = typeof(CostCentre).Assembly;
Context.MetadataWorkspace.LoadFromAssembly(assembly);