I am trying to wrap my head around the idea of Composition. Never used it before. I have a class that looks like this (thinned down):
public class AccountProfile
{
public string AccountNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public void GetAccountProfile()
{
AccountNumber = "123456"; // eventual these will become values from the database
FirstName = "John";
LastName = "Smith";
}
}
Then, in my view model, I'd like to have access to AccountNumber, FirstName, and LastName. I don't want to use inheritance, as this view model will need access to multiple external, unrelated classes. So far the model is simple:
public class AccountProfileViewModel
{
public AccountProfileViewModel() { }
}
Here's what I've tried so far, none which are correct:
public class AccountProfileViewModel
{
AP= new AccountProfile();
public AccountProfileViewModel() { }
}
That one (above) throws multiple errors and won't compile. I've also tried this:
public class AccountProfileViewModel
{
public AccountProfile AP { get; set; }
public AccountProfileViewModel() { }
}
This one (the one above) compiles just fine, but it throws a run-time error in the controller when I try and use it:
model.AP.GetAccountProfile();
The error: {"Object reference not set to an instance of an object."}
I'm out of ideas. Thanks!
you have to initialize the object at least.
public class AccountProfileViewModel
{
public AccountProfile AP { get; set; }
public AccountProfileViewModel() {
AP = new AccountProfile();
}
}
I think what you are trying to achieve is something like this:
public class AccountProfileViewModel
{
public AccountProfile AP { get; set; }
public AccountProfileViewModel() { }
}
or if AccountProfileViewModel really needs AccountProfile you can do
public class AccountProfileViewModel
{
public AccountProfile AP { get; set; }
public AccountProfileViewModel(AccountProfile profile) {
this.AP = profile;
}
}
and in your controller you can do something like this
public class controller {
public ActionResult Index(){
var vm = new AccountProfileViewModel();
var ap = //Get accountProfile
vm.AP = ap;
return View(vm);
}
}
or in the case of example where you need the AccountProfile
public class controller {
public ActionResult Index(){
var ap = //Get accountProfile
var vm = new AccountProfileViewModel(ap);
return View(vm);
}
}
you want AccountProfileViewModel to have an instance of the AccountProfile but you want to set it in the controller.
then in your view you can do Model.AP.AccountNumber for instance
If you need an object reference in this class then it's my personal preference to only create the object if it's required like so:
public class AccountProfileViewModel
{
private AccountProfile _ap;
public AccountProfile AP
{
get { return _ap ?? (_ap = new AccountProfile()); }
set { _ap = value; }
}
}
If you actually use yourObject.AP then it will have a reference created / return the existing one but if it's not used then no reference has been created.
Related
There are already some questions about this problem, but none of them actually solved my problem.
I'm trying to create the Create method of the Student.cs entity, but when I access the create url, this error appears, I really do not know how to solve it.
AlumniController.cs
line error: 32 var teachers = await _contextProfessor.FindAllAsync ();
Image error
Code
AlunoController.cs
public class AlunosController : Controller
{
public readonly AlunosService _contextAluno;
public readonly ProfessorService _contextProfessor;
public readonly TurmasController _contextTurma;
public AlunosController(AlunosService contextAluno)
{
_contextAluno = contextAluno;
}
public async Task<IActionResult> Index()
{
var lista = await _contextAluno.FindAllAsync();
return View(lista);
}
//GET
public async Task<IActionResult> Create()
{
var professores = await _contextProfessor.FindAllAsync();
var turmas = await _contextTurma.FindAllAsync();
var viewModel = new AlunoViewModel {
Professores = professores,
Turmas = turmas
};
return View(viewModel);
}
}
Turma.cs
public class Turma
{
public int Id { get; set; }
public int Numero { get; set; }
public string Curso { get; set; }
public ICollection<Aluno> Alunos { get; set; } = new List<Aluno>();
public Turma()
{
}
public Turma(int id, int numero, string curso)
{
Id = id;
Numero = numero;
Curso = curso;
}
}
Professor.cs
public class Professor
{
public int Id { get; set; }
public string Nome { get; set; }
public string Email { get; set; }
public string Telefone { get; set; }
public ICollection<Aluno> Alunos { get; set; } = new List<Aluno>();
public Professor()
{
}
public Professor(int id, string nome, string email, string telefone)
{
Id = id;
Nome = nome;
Email = email;
Telefone = telefone;
}
}
How can I solve this?
Code Complete HERE.
_contextProfessor is null. You will need to set it in the constructor of AlunosController.
public AlunosController(AlunosService contextAluno, ProfessorService professorService)
{
_contextAluno = contextAluno;
_contextProfessor = processorService;
}
You obviously have not assigned objects to _contextProfessor and _contextTurma fields, so you will naturally get a NullReferenceException if you try to refer to their methods and properties. So, firstly, you need to inject ProfessorService and TurmasController into controller constructor.
But for injection to be successfull, you need to specify the dependecies in your Startup class ConfigureServices method, otherwise the dependecy won't be able to be resolved an InvaidOperationException will be thrown.
Because you forgot to include that service in the call in the constructor
public AlunosController(AlunosService contextAluno, ProfessorService contextProfessor)
//^^^^
{
_contextAluno = contextAluno;
_contextPrefessor = contextProfessor;
}
DI bit you a little. just because you add the one context to the constructor doesn't mean the others are instantiated for free.
i am using Database first method. EDMX file generated default Dbset(TableName) for me.
myDbContext.Table1.ToList();
myDbContext.Table2.ToList();
Can we have a ModelView Class which pull both table out with single line?
Instead of
Table1=myDbContext.Table1.ToList();
Table2=myDbContext.Table2.ToList();
can we have like
ModelView=myDbContext.ModelView;
Updated
public partial class ProductTb
{
public string ProductID { get; set; }
public string ProductArticleNumber { get; set; }
public string ProductName { get; set; }
}
public partial class ProductTbTWO
{
public string ProductID { get; set; }
public string ProductArticleNumber { get; set; }
public string ProductName { get; set; }
}
public class ProductModelView
{
public ProductTb{get;set;}
public ProductTbTWO{get;set}
}
Create a Partial Class of your DbContext and add your custom Code.
public partial class MyDbContext
{
private MyDbContext(string contextName) : base(contextName) { }
public static MyDbContextCreate() {
return new MyDbContext(ContextName);
}
public ProductModelView ModelView {// Get ProductTb and ProductTbTWO}
}
and use it var myDbContext= MyDbContext.Create() and myDbContext.ModelView
But I don't recommend to do something like that, Add a Service class to with public method to get your code, Data Layer shouldn't deal with View Models
i prefer using static class:
public static class Utilities
{
public static ProductModelView getProductViewModel()
{
using (var db = new myDbContext()
{
var vm = new ProductModelView();
vm.ProductTb = db.ProductTb.ToList();
vm.ProductTbTWO = db.ProductTbTWO.ToList();
return vm;
}
}
}
you can call it like:
var vm = Utilities.getProductViewModel();
I got dbset for table Functions in database and FunctionsContext: dbContext. I am implementing repository. In my interface I have only one function at the movement "GetFunctions". I got stuck in implementing class; method "GetFunctions" where I need to call FunctionsContext to get all list of available functions title from database and then send to controller class
I am using mvc5 asp.net and entity framework
dbContext
public class FunctionsContext : dbContext
{
public DbSet<App_Functions> Functions { get; set; }
}
model
[Table("Functions")]
public class App_Functions
{
[Key]
public int Function_ID { get; set; }
[StringLength(50)]
[Required]
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
Domain Class
public class Functions
{
public Functions()
{
}
public int Function_ID { get; set; }
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
IRepository
interface IFunctionRepository: IDisposable
{
IQueryable<Functions> GetFunctions { get; }
}
IRepository Implementation class
public class FunctionRepository : IFunctionRepository
{
private FunctionsContext fun_Context = new FunctionsContext();
public IQueryable<Functions>GetFunctions
{
?????????
}
}
what I want to implement in IQueryableGetFunctions
using (var db = new FunctionsContext())
{
var query = from b in db.Functions
orderby b.Function_ID
select b;
foreach (var item in query)
{
var a2 = item.Title;
}
}
I think the easiest way will be the following:
public IQueryable<Functions> GetFunctions()
{
return fun_Context.Functions.Select(x=>new Functions {
Function_ID = x.Function_ID,
Title = x.Title,
Hierarchy_level = x.Hierarchy_level
});
}
You have to add () after the method name, this declaration does not work 'public IQueryable GetFunctions'
IRepository Implementation class
public class FunctionRepository : IFunctionRepository
{
private FunctionsContext fun_Context = new FunctionsContext();
// For method declaration add the () after the method name
public IQueryable<Functions> GetFunctions()
{
return fun_Context.Functions;
}
}
i have 3 model:
1st one:
public class CreateFieldModel
{
public FieldModel fm { get; set; }
public CategoryModel cm { get; set; }
}
2nd one:
public class FieldModel
{
public string field_Name { get; set; }
public InputTypeModel itm { get; set; }
public string input1 { get; set; }
public string input2 { get; set; }
public string input3 { get; set; }
public string input4 { get; set; }
public List<InputTypeModel> inputs { get; set; }
}
3rd One:
public class InputTypeModel
{
public string inputTypeName { get; set; }
public string inputTypeDesc { get; set; }
}
2 methods:
1st One:
public List<InputTypeModel> getInputTypes()
{
var inptypes = edu.InputTypes;
List<InputTypeModel> listInputTypes = new List<InputTypeModel>();
foreach (var inpType in inptypes)
{
listInputTypes.Add(new InputTypeModel { inputTypeName = inpType.Input_Type_Name, inputTypeDesc = inpType.Input_Type_Description });
}
return listInputTypes;
}
when this method executes listInputTypes has three different values.. i check it by debugging.. so no roblem here. This methos is under the class FormManagement.. I am calling this method from the following action method:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
when cfm.fm.inputs = ffm.getInputTypes(); executes it is showing "Object reference not set to an instance of an object." message... I am quite beginner to mvc.. please help
Without knowing what you really want to achieve with cfm-parameter in your action, the only thing I can suggest is to check for null references and create new instances before you assign them:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
if (cfm == null)
{
cfm = new CreateFieldModel();
}
if (cfm.fm == null)
{
cfm.fm = new FieldModel();
}
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
Of course, this supposes that your not relying on incoming data through your route parameters. If you are, you need to check why the values are not getting passed in, but I'm guessing you don't need it as a parameter in the first place.
I have something like this
public class AViewModel
{
public decimal number { get; set; }
public List<BViewModel> BVM { get; set; }
}
public class BViewModel
{
public string someString{ get; set; }
}
public class SomeObject
{
public decimal number { get; set; }
public List<OtherObjects> BVM { get; set; }
}
public class OtherObjects {
public string someString{ get; set; }
}
Mapper.CreateMap<SomeObject,AViewModel>();
When I have this I get
Trying to map OtherObjects to BViewModel
Using mapping configuration for SomeObject to AViewModel
Destination property: BVM
Missing type map configuration or unsupported mapping.
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
How can I help it figure out how to map it properly?
I believe Automapper needs to know how to convert OtherObject to BViewModel. Try adding a mapping for that too.
You need to specify a typeconverter between OtherObject and BViewModel by specifying a custom type converter
Here's what the converter would look like:
public class OtherToBViewTypeConverter : ITypeConverter<OtherObjects, BViewModel>
{
public BViewModel Convert(ResolutionContext context)
{
if (context.IsSourceValueNull) return null;
var otherObjects = context.SourceValue as OtherObjects;
return new BViewModel { someString = otherObjects.someString; }
}
}
And then the map would be called like this:
Mapper.CreateMap<SomeObject,AViewModel>().ConvertUsing<OtherToBViewTypeConverter>();