I'm starting to working on ASP.NET using MVC. I writing to action results, one of them is a HTTP GET and the another HTTP POST
[HttpGet]
public ActionResult DoTest()
{
Worksheet worksheets = new worksheets(..);
return View(w);
}
[HttpPost]
public ActionResult DoTest(Worksheet worksheet)
{
return PartialView("_Problems", worksheet);
}
Now, Worksheet class has a property called Problems and this is a collection, but uses as an abstract class item.
public class Worksheet
{
public List<Problem> Problems { get; set; }
}
Here's my abstract class and one implementation
public abstract class Problem
{
public Problem() { }
public int Id { get; set; }
public abstract bool IsComplete { get; }
protected abstract bool CheckResponse();
}
public class Problem1 : Problem
{
...
public decimal CorrectResult { get; set; }
// this is the only property of my implementation class which I need
public decimal? Result { get; set;}
public override bool IsComplete
{
get { return Result.HasValue; }
}
protected override bool CheckResponse()
{
return this.CorrectResult.Equals(this.Result.Value);
}
}
I have right now, many implementations of Problem class, but I really need to get just one value of my implementation class. But it thrown the above image error.
What can I do to allow model binder recover that part of my abstracts classes
The following code would not compile:
var problem = new Problem();
... because the Problem class is abstract. The MVC engine cannot just create a Problem directly. Unless you give it some way to know which type of Problem to instantiate, there's nothing it can do.
It is possible to create your own ModelBinder implementation, and tell MVC to use it. Your implementation could be tied to a Dependency Injection framework, for example, so that it knows to create a Problem1 whenever a Problem class is requested.
Or you could simply change your action method to take a concrete type:
public ActionResult DoTest(IEnumerable<Problem1> problems)
{
return PartialView("_Problems",
new Worksheet {
Problems = problems.Cast<Problem>().ToList()
});
}
Related
I am using MetadataType to define Json.NET attributes for the following type, then serializing it using Json.NET inside its ToString() method:
namespace ConsoleApp1
{
public interface ICell
{
int Id { get; }
}
public interface IEukaryote
{
System.Collections.Generic.IEnumerable<ICell> Cells { get; }
string GenericName { get; }
}
public sealed partial class PlantCell
: ICell
{
public int Id => 12324;
}
public sealed partial class Plant
: IEukaryote
{
private readonly System.Collections.Generic.IDictionary<string, object> _valuesDict;
public Plant()
{
_valuesDict = new System.Collections.Generic.Dictionary<string, object>();
var cells = new System.Collections.Generic.List<PlantCell>();
cells.Add(new PlantCell());
_valuesDict["Cells"] = cells;
_valuesDict["GenericName"] = "HousePlant";
}
public System.Collections.Generic.IEnumerable<ICell> Cells => _valuesDict["Cells"] as System.Collections.Generic.IEnumerable<ICell>;
public string GenericName => _valuesDict["GenericName"] as string;
public int SomethingIDoNotWantSerialized => 99999;
public override string ToString()
{
return Newtonsoft.Json.JsonConvert.SerializeObject(this,
new Newtonsoft.Json.JsonSerializerSettings()
{
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
}
);
}
}
[System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))]
public sealed partial class Plant
{
[Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
internal sealed class PlantMetadata
{
[Newtonsoft.Json.JsonProperty]
public System.Collections.Generic.IEnumerable<ICell> Cells;
[Newtonsoft.Json.JsonProperty]
public string GenericName;
//...
}
}
class Program
{
static void Main(string[] args)
{
var plant = new Plant();
System.Console.WriteLine(System.String.Format("Output is {0}", plant.ToString()));
System.Console.ReadKey();
}
}
}
My problem is that Plant.ToString() will return '{}'. Why is that? It was working before. The only change I made was in PlantMetadata where I altered the MemberSerialization to OptIn instead of OptOut, as I had less properties I wanted included than left out.
As stated by Newtonsoft in this issue, MetadataTypeAttribute attributes are in fact supported by Json.NET. However, it appears that Json.NET requires that the MetadataClassType members must be properties when the corresponding "real" members are properties, and fields when the corresponding "real" members are fields. Thus, if I define your Plant type as follows, with two properties and one field to be serialized:
public sealed partial class Plant : IEukaryote
{
public System.Collections.Generic.IEnumerable<ICell> Cells { get { return (_valuesDict["Cells"] as System.Collections.IEnumerable).Cast<ICell>(); } }
public string GenericName { get { return _valuesDict["GenericName"] as string; } }
public string FieldIWantSerialized;
public int SomethingIDoNotWantSerialized { get { return 99999; } }
// Remainder as before.
Then the PlantMetadata must also have two properties and one field for them to be serialized successfully:
//Metadata.cs
[System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))]
public sealed partial class Plant
{
[JsonObject(MemberSerialization.OptIn)]
internal sealed class PlantMetadata
{
[JsonProperty]
public IEnumerable<ICell> Cells { get; set; }
[JsonProperty]
public string GenericName { get; set; }
[JsonProperty]
public string FieldIWantSerialized;
}
}
If I make Cells or GenericName be fields, or FieldIWantSerialized be a property, then they do not get opted into serialization.
Sample working .Net Fiddle.
Note that, in addition, I have found that the MetadataClassType properties apparently must have the same return type as the real properties. If I change your PlantMetadata as follows:
[JsonObject(MemberSerialization.OptIn)]
internal sealed class PlantMetadata
{
[JsonProperty]
public object Cells { get; set; }
[JsonProperty]
public object GenericName { get; set; }
[JsonProperty]
public object FieldIWantSerialized;
}
Then only FieldIWantSerialized is serialized, not the properties. .Net Fiddle #2 showing this behavior. This may be a Newtonsoft issue; as stated in the Microsoft documentation Defining Attributes in Metadata Classes:
The actual type of these properties is not important, and is ignored
by the compiler. The accepted approach is to declare them all as of
type Object.
If it matters, you could report an issue about the return type restriction to Newtonsoft - or report an issue asking that details of their support for MetadataTypeAttribute be more fully documented.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I am working on implementing Repository Pattern and UnitOfWork from last few days, which I have completed to upto good extend, I believe. I am sure there are plenty of ways to implement that but what I am interesting to find best approach for that.
I am taking very simple example coded in ASP.NET MVC 5 using visual studio 2013. my main focus of question is implementation of UnitOfWork. is it advisable to use multiple UnitOfWorks for each business concerns implementing repository functions in private method and giving away public functions for controller to use????
I have function table (SQL Server) in the controller class via generic repository. I have IGenericRepository which has IQueryable one function, I have GenericRepository class where i am implementing this interface. I got FunctionContext which is inherited from baseContext. The reason i have baseContext so all the dbcontexts can use one path to hit database but same time keep number of table limited to business need.
now in my approach;
One BaseContext : DbContext
multiple DbContext, bundling all required table to individual business concern that extend BaseContext
Generic Repository Interface (CRUD)
Generic Repository Implementation class
specific Repository class, extending Generic Reposirtory in case require more function on top of CRUD operations.
Individual UnitOfWork --> taking to required repository/ repositories in private method and provide public method only for using functions
Controller call require UnitOfWork to use public methods.
in following program, all i am getting list of function title and passing to controller to print
Generic Repository Interface
public interface IGenericRepository<TEntity> : IDisposable
{
IQueryable<TEntity> GetAll();
}
Generic Repository
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
protected DbSet<TEntity> _DbSet;
private readonly DbContext _dbContext;
public GenericRepository()
{
}
public GenericRepository(DbContext dbContext)
{
this._dbContext = dbContext;
_DbSet = _dbContext.Set<TEntity>();
}
public IQueryable<TEntity> GetAll()
{
return _DbSet;
}
public void Dispose()
{
}
}
BaseContext
public class BaseContext<TContext> : DbContext where TContext : DbContext
{
static BaseContext()
{
Database.SetInitializer<TContext>(null);
}
protected BaseContext()
: base("name = ApplicationDbConnection")
{ }
}
FunctionContext
public class FunctionsContext : BaseContext<FunctionsContext>
{
public DbSet<App_Functions> Functions { get; set; }
}
Function Mapping class
[Table("Functions")]
public class App_Functions
{
public App_Functions()
{
}
[Key]
public int Function_ID { get; set; }
[StringLength(50)]
[Required]
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
Function Domain class
public class Functions
{
public Functions()
{
}
public int Function_ID { get; set; }
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
Function_UnitOfWork
public class Function_UnitOfWork
{
private GenericRepository<App_Functions> _function_Repository = new GenericRepository<App_Functions>(new FunctionsContext());
public Function_UnitOfWork()
{
}
private List<Functions> getAllFunctionsFromRepository()
{
List<Functions> query = new List<Functions>();
query = _function_Repository.GetAll().Select(x => new Functions
{
Function_ID = x.Function_ID,
Title = x.Title,
Hierarchy_level = x.Hierarchy_level
}).ToList();
return query;
}
public List<Functions>GetAllFunctions()
{
return getAllFunctionsFromRepository();
}
}
Controller class
public class HomeController : Controller
{
public ActionResult Index()
{
Function_UnitOfWork UOF = new Function_UnitOfWork();
var a1 = UOF.GetAllFunctions();
foreach(var item in a1)
{
var b1 = item.Title;
}
return View();
}
}
While it is opinion based, just the name of of Unit Of Work pattern suggest limited timespan of the object. So the use of it in controller should be something like
public ActionResult Index()
{
using(var UOF = new Function_UnitOfWork()) {
var a1 = UOF.GetAllFunctions();
foreach(var item in a1)
{
var b1 = item.Title;
}
}
return View();
}
Also one approach we use is (in short)
public class DataObject { }
public class Repo: IRepo<T> where T: DataObject
public class RepoController<T> : Controller where T: DataObject {
protected IRepo<T> Repo;
}
So controllers will be generic and will have field for particular repo
You will use some dependency injection tool, like ninject or mef to bound controllers with repos behind the scene.
Building on Ladislav's answer to
Entity Framework Code First and Collections of Primitive Types
I'm attempting to create a wrapper type EfObservableCollection<T> around an ObservableCollection<T> that has an additional helper property to simplify persistence (certainly this solution has trade-offs, but it's seems workable for my domain).
However, properties of type EfObservableCollection<T> seem to be ignored by EF. No appropriate columns are created in the database. Guessing that implementing IEnumerable<T> might trigger EF to ignore that type, I commented out that implementation with no change in behavior.
What am I missing here?
Entity Class
public class A
{
[DataMember]
public long Id { get; set; }
[DataMember]
public string Text { get; set; }
// Tags is not persisted
[DataMember]
public EfObservableCollection<string> Tags { get; set; }
}
Wrapper Class
[ComplexType]
public class EfObservableCollection<T> : IEnumerable<T>
{
const string VALUE_SEPARATOR = "\x8"; // Backspace character. Unlikely to be actually entered by a user. Assumes ASCII or UTF-8.
readonly string[] VALUE_SEPARATORS = new string[] { VALUE_SEPARATOR };
[NotMapped]
protected ObservableCollection<T> Collection { get; private set; }
public EfObservableCollection()
{
Collection = new ObservableCollection<T>();
}
[DataMember]
public string PersistHelper
{
get
{
string serializedValue = string.Join(VALUE_SEPARATOR, Collection.ToArray());
return serializedValue;
}
set
{
Collection.Clear();
string[] serializedValues = value.Split(VALUE_SEPARATORS, StringSplitOptions.None);
foreach (string serializedValue in serializedValues)
{
Collection.Add((T)Convert.ChangeType(serializedValue, typeof(T))); // T must implement IConvertable, else a runtime exception.
}
}
}
public void Add(T item)
{
Collection.Add(item);
}
IEnumerator<T> GetEnumerator()
{
return Collection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
It turns out that Entity Framework does not like the generic class EfObservableCollection<T>.
If I derive a non-generic class from that class, data is persisted as expected:
[ComplexType]
public class EfObservableCollectionString : EfObservableCollection<string>
{
}
Joining backspace with list of strings causes cleaning last character in each string item.
I think serialization to json using System.Web.Script.Serialization.JavaScriptSerializer is better.
I have an application that have EF 16 classes that share this information: They all are classes only with a key field and a description.
I think it should be a waste if I make a controller with just 1 method just to present a form to fill these classes info, then I was thinking in to make a generic form(with key, description) and dynamically fill the right class through a sort of selection the selected info in any way, any good suggestion or pattern to do that? Where the generic methods should be located.
Have you looked into MVC templates? You should be able to use templates to automatically "generate" your Edit and Display Views. No need to create a distinct View for each of your classes.
I had similar situation and did it almost like that:
interface IKeyDescription
{
int Key { get; set; }
string Description { get; set; }
}
public partial class Class1 : IKeyDescription;
public partial class Class2 : IKeyDescription;
public abstract class BaseKeyDescriptionController<T> where T : IKeyDescription
{
[Inject]
public IKeyDescriptionService<T> Service { get; set; }
[HttpGet]
public ActionResult List()
{
//View is stored in shared folder
return View("List",Service.List());
}
[HttpPost]
public ActionResult List(IList<T> elements)
{
Service.Save(elements);
....
}
}
public class Class1Controller : BaseKeyDescriptionController<Class1>
{
}
public class Class2Controller : BaseKeyDescriptionController<Class2>
{
}
View will inherit from System.Web.Mvc.ViewPage<IKeyDescription>.
I am creating a example for better understanding.
[CustomValidator("Property1","Property2", ErrorMessage= "Error1")]
[CustomValidator("Property3","Property4", ErrorMessage= "Error1")]
public class MyViewModel
{
public string Property1 {get; set;}
public string Property2 {get; set;}
public string Property3 {get; set;}
public string Property4 {get; set;}
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class CustomValidator : ValidationAttribute
{
All the required stuff is written.
}
Only the second validator (or the last one in the list) gets fired and ignores the first one.
I am not sure if this is the right approach for this scenario.
Any suggestions?
if you are using Linq to SQL why not try something like this
add a rule violations class to handle rule violations
public class RuleViolation
{
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
public RuleViolation(string errorMessage)
{
ErrorMessage = errorMessage;
}
public RuleViolation(string errorMessage, string propertyName)
{
ErrorMessage = errorMessage;
PropertyName = propertyName;
}
}
now on your data class
[Bind(Exclude="ID")]
public partial class Something
{
public bool IsValid
{
get { return (GetRuleViolations().Count() == 0); }
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
if (String.IsNullOrEmpty(Name.Trim()))
yield return new RuleViolation("Name Required", "Name");
if (String.IsNullOrEmpty(LocationID.ToString().Trim()))
yield return new RuleViolation("Location Required", "LocationID");
yield break;
}
partial void OnValidate(ChangeAction action)
{
if (!IsValid)
throw new ApplicationException("Rule violations prevent saving");
}
}
and in your controller's methods for updating, use the updatemodel method for changing properties
Something something = somethingRepo.GetSomething(id);
try
{
//update something
UpdateModel(something);
somethingRepo.Save();
return RedirectToAction("Index");
}
catch
{
ModelState.AddRuleViolations(something.GetRuleViolations());
return View(something);
}
this way you can just add rules to your data class as it changes and it will be reflected in your updates, etc
I found another question that answers this. You have to override Attribute.TypeId.
Custom validation attribute with multiple instances problem
you dont really need all that code use data annotations by creating a metaData class for your model link text
that should set you on the right road also read up on html helpers and buddy classes ( this is what they call em)
I had the same problem.
I come up with the following solution.
Your POCO class might implement interface IValidatableObject.
This requires from you to implement the following method.
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// return list of appropriate ValidationResult object
var customResult = new List<ValidationResult>();
customResult.Add(new ValidationResult("message", new List<string>(){"Property1"});
}
You can place any validation logic there. This has also the advantage over class-level attribute. Class-level attribute can only be shown in ValidationSummary (they are not related to any property). In contrast to it you can set specific members while returning ValidationResult. This allows to show validation information beside specific control to which the message concerns.