This is a follow up to this:
What does MVC3 do with C# Optional Parameters?
I have an action with the following signature:
public ViewResult Show(int Id, PublishingErrorSummary pubErrors=null, String title=null)
On requesting server/show/1 pubErrors is not null, but title is null. How is it possible? These are just two objects but string somehow manages to become null. Where can I fix this?
Edit: class definition added
public class PublishingErrorSummary
{
public List<string> StepOneErrors { get; set; }
public List<string> StepTwoErrors { get; set; }
public List<string> StepThreeErrors { get; set; }
public List<string> StepFourErrors { get; set; }
}
PublishingErrorSummary is a complex object. The default model binder always initializes complex objects. It doesn't really make sense to set its default value to null. Same stands for the title parameter. Strings are reference types and their default value will be null anyway if no request parameter title is sent.
Related
I have this controller method:
public JsonNetResult Save(MyModel provider)
{
return GetJson(_serviceProviderService.Save(provider));
}
I post this json (captured via Fiddler):
{"Id":100,"Name":"Foo", "CreatedDate":"2013-02-20T15:32:07.85", "Models":null}
When reaching the Save method in the controller (breakpoint) the property Models has become an an empty collection.
I want to keep the null value on the Models property. How do I do that?
Reason: I want treat the null value as the Models collection was not "loaded" and will not be affected when saving the object graph; It should only be affected when it contains items.
Here is the ViewModel:
public class MyModel
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public List<EntityDisplayNameModel> Models { get; set; }
}
I need to return a collection with nested optional collections from my WebAPI and convert it back to objects in my Web UI, however I'm getting the following error:
Cannot create and populate list type System.Linq.IQueryable`1[MyNamespace.MyClass].
I'm using Json.Net.
Here is a sample of my code:
public class ClassA
{
public Int64 Id { get; set; }
public String Description { get; set; }
public IEnumerable<ClassB> { get; set; }
}
public class ClassB
{
public Int64 Id { get; set; }
public String Description { get; set; }
}
I've saw some questions here in stackoverflow, but I don't have access to serialization options (it is handled internally by our library).
UPDATE
I've forgot to mention that ClassA is returned as an IQueryable in my Web API.
Changing the return type of my Web API method to IEnumerable instead of IQueryable solved the problem.
I think I am missing a simple solution here. When I run a select (using Linq-style on IQueryable) that returns IQueryable, I may want MyClass to return differently-formatted key/values than I will use in my insert.
Consider as example the below UploadFile class and note properties id and Filetimestamp. When I SET Filetimestamp I want it stored as DateTime, but when I RETRIEVE IQueryable I would like to:
See Filetimestamp returned as String
OR
See a separate property returned as String reflecting Filetimestamp.toString(). This property doesn't have a corresponding key in the database; it's just a decoration of a real key/value from BSON.
Thinking #1 was unlikely, I pursued #2 by adding a get-only field Filetimestamp_str that returns Filetimestamp.toString(). When I select, behavior is as expected. When I insert, I see failures.
I could create a decorator class that I use for gets and all would work - but am I missing something more fundamental and simple here?
public class UploadFile : IUploadFile
{
public Object _id { get; set; }
public String Filepath { get; set; }
public String Filename { get; set; }
public String Filetype { get; set; }
public String Fileauthor { get; set; }
public DateTime Filetimestamp { get; set; }
public Object FileID { get; set; }
// these keys are not in DB
public String Filetimestamp_str { get { return Filetimestamp.ToString(); } }
public String _id_str { get { return _id.ToString(); } }
}
You could create a BsonClassMap, specifying which properties should (not) be serialized. See the Serialization Tutorial. However, according to that tutorial, a read-only property should not be automapped, so I should not expect errors on the insert.
I have an abstract class
public abstract class Member
{
public string ID { get; set; }
public string Username { get; set; }
public int MemberType { get; set; }
public abstract string MemberName { get; set; }
public int Status { get; set; }
}
public class Person : Member
{
public string LastName { get; set; }
public string FirstName{ get; set; }
}
public class Business : Member
{
public string BusinessName { get; set; }
public string TaxNo { get; set; }
}
The class was mapped using fluent API,
Now, is there a way to update the "Status" property from the view(having Member model) without using or going to a subclass (Person/Business)?
I just tried it, but it says "Cannot create an abstract class.", when submitting the page.
Or there is a correct way to do this?
Thanks
Not in EF. You have to instantiate an object to work with EF, and you can't instantiate an abstract class.
You could make the class not be abstract. Or you could use a stored proc to update the field, or some direct sql.
It sounds like your problem is that your action method has an abstract type as a parameter, which the default model binder can't do anything with. If you are dead set on using the same view for two different classes, you may need to implement your own model binder to inspect in the incoming request and decide which type, Person or Business, to instantiate.
Check out this link for more information on creating a custom model binder:
http://odetocode.com/blogs/scott/archive/2009/05/05/iterating-on-an-asp-net-mvc-model-binder.aspx
This seems like a similar problem to the one I've answered previously here:
ASP.NET MVC 3: DefaultModelBinder with inheritance/polymorphism
I have a class like this
public class PageReference {
[ScaffoldColumn(false)]
public string Id { get; set; }
public string Name { get; set; }
}
and in my model I use it like this
[Required]
public PageReference PageLink { get; set; }
the required attribute does not fire if I add it to the pagelink property, how can this be solved?
The validation attribute is evaluated by the model binder against the data supplied by the value provider (often posted form fields). If you're posting a form that does not include that field, the binder won't touch that property of the model and so won't evaluate the validation attributes.
I think there is no recursive validation support in asp.net mvc