In my Action, I have an error of type System.MissingMethodException when I use TryUpdateModel.
I use this in several place in my Controller without issue, so it mean a problem on my model ?
In this case, I use a derived class from my domain.
public class TypeOperationDisplay : TypeOperation
{
public TypeOperationDisplay(TypeOperation to)
{
Id = to.Id;
Code = to.Code;
Libelle = to.Libelle;
LibelleSaisie = to.LibelleSaisie;
}
[ScaffoldColumn(false)]
public override long Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
[HtmlPropertiesAttribute(MaxLength=255, Size=50, ReadOnly=true)]
[DisplayName("")]
public override string Code
{
get
{
return base.Code;
}
set
{
base.Code = value;
}
}
}
TypeOperation is generated. I derive from this class to add Attributes and I use this next in my Model.
public class DetailTypeOperationModel : ViewModelBase
{
public Int64 IdTypeOperation { get; set; }
public TypeOperationDisplay TypeOperationDisplay { get; set; }
}
To show, I use this Action
public ActionResult AfficheDetailTypeOperation(Int64 idTypeOperation)
{
DetailTypeOperationModel d = new DetailTypeOperationModel
{
IdTypeOperation = idTypeOperation,
TypeOperationDisplay = _srvTypeOperation.Charger(idTypeOperation).ToDisplay()
};
return View("GererTypeOperation", d);
}
To retrieve datas sent
[HttpPost]
public ActionResult ModifieTypeOperation(Int64 idTypeOperation, FormCollection fc)
{
DetailTypeOperationModel d = new DetailTypeOperationModel();
TryUpdateModel<DetailTypeOperationModel>(d);
_srvTypeOperation.Modifier(d.TypeOperationDisplay);
return View("Index", new AdministrationModel());
}
And it's on this Action, that I have issue on TryUpdateModel.
With step by step debug, I can't see why this component catch an error and where is this missing method ?
Thanks for helping :)
Make your TypeOperationDisplay property virtual in your DetailTypeOperationModel class.
public class DetailTypeOperationModel : ViewModelBase
{
public Int64 IdTypeOperation { get; set; }
public virtual TypeOperationDisplay TypeOperationDisplay { get; set; }
}
I am guessing here, but my theory is that EF is trying to create a proxy of DetailTypeOperationModel, and can't because your own class property is not virtual.
Related
I have a problem to get the right OpenApi definition aftr update from 5.0.0 to 5.4.1
We had custom Polymorphism filter with 5.0.0 version, but they does not work correct with latest one. So I removed them and started to use GeneratePolymorphicSchemas(). It does what I need for our polymorphic models but not just for them. We have also some other abstract and concrete classes, where we don't need type discriminator. I tried different configurations but without any success. Either the generated definition is wrong or I get error on swagger UI or a server 503 error.
Link to the sample project Sample project
Here are my polimorhic models
namespace SwashbuckleTest.Models
{
public interface ITypeDiscriminator
{
string TypeDiscriminator { get; }
}
public abstract class SurveyStep : ITypeDiscriminator
{
public virtual string Id { get; set; }
public string TypeDiscriminator => GetType().Name;
}
public abstract class SurveyStepResult : ITypeDiscriminator
{
public string Id { get; set; }
public string TypeDiscriminator => GetType().Name;
}
public class BoolStep : SurveyStep
{
private string _id;
public BoolStep()
{
ResultObject = new BoolStepResult();
}
public override string Id
{
get => _id;
set
{
_id = value;
ResultObject.Id = value;
}
}
public string Question { get; set; }
public BoolStepResult ResultObject { get; }
}
public class BoolStepResult : SurveyStepResult
{
public bool Value { get; set; }
}
}
Here other models
namespace SwashbuckleTest.Models
{
public abstract class SomeBaseModel
{
public string BaseValue { get; set; }
}
public class SomeConcreteModel : SomeBaseModel
{
public int ConcreteValue { get; set; }
}
}
and configurations I have tried
options.UseAllOfToExtendReferenceSchemas();
options.GeneratePolymorphicSchemas(t =>
{
var types = t.Is<SurveyStep>() ? new List<Type>() {typeof(BoolStep)}
: t.Is<SurveyStepResult>() ? new List<Type>() {typeof(BoolStepResult)}
: null;
return types;
} , t => t.Is<ITypeDiscriminator>() ? nameof(ITypeDiscriminator.TypeDiscriminator).ToCamelCase() : null);
// or
options.GeneratePolymorphicSchemas(discriminatorSelector: t => t.Is<ITypeDiscriminator>() ? nameof(ITypeDiscriminator.TypeDiscriminator).ToCamelCase() : null);
I found the problem by my self.
The Is<> extension method does not filter abstract classes so we got here endless recursion.
It helped us to generate swagger.json, but we got other problems, that are little bit deeper.
I have 2 base classes which 1 for search criteria and other 1 for search results.
I also have 2 derived classes for User object versions of both of those.
When I put a breakpoint in the controller action I can see all properties are populated as I've hardcoded.
When I call this action directly in the browser, each of my derived object properties is null.
I'm guessing the JSON serialization is not able to tell the difference from the base class to the derived one.
Is there a way to solve this?
public class BaseSearchCriteria
{
public int Page { get; set; }
public int RecordsPerPage { get; set; }
}
public class BaseSearchResults
{
public int TotalResults { get; set; }
public virtual BaseSearchCriteria SearchCriteria { get; set; }
}
public class UserSearchCriteria : BaseSearchCriteria
{
public string Username { get; set; }
}
public class UserSearchResults : BaseSearchResults
{
public new UserSearchCriteria SearchCriteria { get; set; }
}
public JsonResult Search(UserSearchCriteria model)
{
var viewModel = new UserSearchResults
{
SearchCriteria = new UserSearchCriteria
{
Page = 1,
RecordsPerPage = 15
}
};
viewModel.TotalResults = 100;
return Json(viewModel, JsonRequestBehavior.AllowGet);
}
Maybe good way to deal with it is to use generics as Daniel A. White propose.
Sample gist here.
Environment:
MVC4
C#
VS2010
Problem:
I have an interface that I am considering my "Base" Interface that is defined as follows:
public interface ITestModel
{
TestViewModel model { get; set; }
void PopulateNewReferralRequestModel(Int32 ReferralTypeID, Int32 profileid, string UniqueKeyValues);
void Save();
}
[MetadataType(typeof(MetaData_TestViewModel))]
public partial class TestViewModel
{
public Int32 id { get; set; }
public string name { get; set; }
public string comments { get; set; }
}
public class MetaData_TestViewModel
{
[Required(ErrorMessage = "ID is required")]
[DisplayName("Primary Key")]
public Int32 id { get; set; }
[Required(ErrorMessage = "Name is required")]
[DisplayName("New Name")]
public string name { get; set; }
[DisplayName("Comments")]
public string comments { get; set; }
}
Using the interface:
If I do the following everything works as I want:
public class BaseViewModel : ITestModel
{
private TestViewModel _model;
public TestViewModel model
{
get { return _model; }
set { _model = value; }
}
public void PopulateNewReferralRequestModel(Int32 ReferralTypeID, Int32 profileid, string UniqueKeyValues)
{
model = new TestViewModel();
model.id = ReferralTypeID;
model.name = "TEst";
model.comments = "This is a comment";
}
public void Save()
{
int i = 1;
return;
}
}
Now I want to inherit the "Base" Interface but change the definition of model property with a definition that is inherited from the TestViewModel as follows:
public interface ITestModelB : ITestModel
{
new TestViewModelB model { get; set; }
}
public class TestViewModelB : TestViewModel
{
public int anotherfield { get; set; }
public string anotherstringfield { get; set; }
}
And use the interface as follows:
public class AViewModel : ITestModelB
{
private TestViewModelB _model;
public TestViewModelB model
{
get
{
return _model;
}
set
{
_model = value;
}
}
public void PopulateNewReferralRequestModel(Int32 ReferralTypeID, Int32 profileid, string UniqueKeyValues)
{
model = new TestViewModelB();
model.comments = "New model created";
model.id = 1;
model.name = "Referral Type 1";
model.anotherfield = profileid;
model.anotherstringfield = UniqueKeyValues;
}
public void Save()
{
int i = 1;
return;
}
}
The problem is when I build I get the following error:
Error 1 'InterfaceTest.Models.AViewModel' does not implement interface member 'InterfaceTest.Models.ITestModel.model'. 'InterfaceTest.Models.AViewModel.model' cannot implement 'InterfaceTest.Models.ITestModel.model' because it does not have the matching return type of 'InterfaceTest.Models.TestViewModel'.
Why I want to do this:
I have a referral system that I am trying to build where all referrals have the same base properties and actions. Each referral type also has properties and actions specific to the referral type. I want the referrals to flow through the same controllers so that when a new referral is added, I only have to create a new interface to handle the referral.
Here is what I want to be able to do in my controllers:
ITestModel model = businessLogic.GetModel(referraltypeid);
model.PopulateNewReferralRequestModel(1, 1234, "DRC Policy, 12345678, 2/14/2014");
I would use a method in my businessLogic class to determine which model type to return based on the referral type. All models would implement the ITestModel interface. Doing this would allow me to handle all referrals through the same controller rather than having to have multiple controllers for each referral type.
What I need
Can anyone tell me how to overcome the error I'm getting when I build or suggest another solution for what I want to accomplish?
Any help is greatly appreciated!
You can get rid of an compile error using explicit interface implementation
public class AViewModel : ITestModelB
{
private TestViewModelB _model;
public TestViewModelB model
{
get
{
return _model;
}
set
{
_model = value;
}
}
private TestViewModel newmodel;
TestViewModel ITestModel.model
{
get { return newmodel; }
set { newmodel = value; }
}
public void PopulateNewReferralRequestModel(Int32 ReferralTypeID, Int32 profileid, string UniqueKeyValues)
{
model = new TestViewModelB();
model.comments = "New model created";
model.id = 1;
model.name = "Referral Type 1";
model.anotherfield = profileid;
model.anotherstringfield = UniqueKeyValues;
}
public void Save()
{
int i = 1;
return;
}
}
Or maybe use generic interface
public interface ITestModel<Tmodel>
{
Tmodel model { get; set; }
void PopulateNewReferralRequestModel(Int32 ReferralTypeID, Int32 profileid, string UniqueKeyValues);
void Save();
}
I am using StructureMap for my dependency resolving. I am faced with an issue I don't know how to solve as the only way to make a form posting I understand will end up being without dependency injection which negate the whole essence of having StructureMap in my project.
The error is that I don't have Add method in my IdbContext Model. Below is my approach.
I have a Model named Module defined as below
public class Module
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual DateTime? DateCreated { get; set; }
public virtual string ModuleDescription { get; set; }
}
and an interface defined as below.
public interface ISolnetDataSource
{
IQueryable<Module> Modules { get; }
void Save();
}
A DbContext like below
public class CMSDB : DbContext, ISolnetDataSource
{
public CMSDB() : base("DefaultConnection")
{
}
public DbSet<Module> Modules { get; set; }
void ISolnetDataSource.Save()
{
SaveChanges();
}
IQueryable<Module> ISolnetDataSource.Modules
{
get { return Modules; }
}
}
and my controller defined as
[HttpPost]
public ActionResult Index(CreateModulesViewModels module)
{
ViewBag.ListModule = _db.Modules.ToList();
if (ModelState.IsValid)
{
var model = new CreateModulesViewModels();
var CreateModule = new Module();
CreateModule.Name = module.Name;
CreateModule.ModuleDescription = module.ModuleDescription;
CreateModule.DateCreated = DateTime.Now;
//_db.modules.Add(CreateModule);
_db.Save();
return View(model);
}
return View(module);
}
The challenge I have with this is that I could'nt do _db.modules.Add(CreateModule) (the commented line in the controller) so as to add a new record. What I'm doing wrong. I want to do this using the best approach applicable.
What about:
_db.modules.Entry(CreateModule).State = System.Data.EntityState.Added;
How can i expose the return of my method in to a class property?
public class BIContactLib: ContactLib
{
//Expose it here.. to replace the code below
public IEnumerable<BIContactLib> GetContactLibs
{
get { return (BIContactLib) GetAll}
set { ; }
}
}
public class BIContactLibService : IBIRequirement, IDisposable
{
private ClientContext context = new ClientContext();
//The return of the method here is the one I would like to expose
public IEnumerable<BIContactLib> GetAll()
{
var contactslib = context.ContactLibs;
return contactslib.ToList();
}
}
The reason behind this, is I want to create a view model with have the list of contacts library... heres my view model by the way..
public class PersonInformation
{
public BIPerson Person { get; set; }
public BIAddress Address { get; set; }
//This is where i want to use it
public IEnumerable<BIContactLib> GetAll { get; set; }
}
Or any other way to do this?
Best regards,
How about something like this
public IEnumerable<BIContactLib> GetContactLibs
{
get {
BiContractLib lib = new BiContractLib();
return lib.GetAll();
}
}