I have a class
public class LookupClass {
public int Id { get; set; }
public string Name { get; set; }
}
That I have referenced in another class
public class Sampleclass {
public int Id { get; set; }
public LookupClass LookupEntry { get; set; }
}
which is is displayed in a KendoUI Grid
#(Html.Kendo().Grid<SampleClass>()
.Name("SomeGrid")
.Columns(cols => {
cols.Bound(o => o.LookupEntry).Title("Lookup Column") // Displays [object Object]
cols.Bound(o => o.LookupEntry.Name) // displays name correctly
}
.DataSource(datasource =>
// leaving this out since the data is seems to be loading correctly.
)
)
When displaying the grid it just displays [object Object] for the value in the cells in the "Lookup Column" column. I have gotten the editor template working (leaving out code since not necessary, basically copied from here) and saving/loading works (left out for simplicity), but I can't seem to figure out how to display the Name property from the Lookup class.
Found a KendoUI example that shows how to do this (http://demos.kendoui.com/web/grid/editing-custom.html)
Basically you have to use a ClientTemplate to display the property you want to display
#(Html.Kendo().Grid<SampleClass>()
.Name("SomeGrid")
.Columns(cols => {
cols.Bound(o => o.LookupEntry).ClientTemplate("#=LookupEntry.Name#").Title("Lookup Column")
}
)
On a side note, if you try to create a new record, it will produce an error about not finding LookupEntry (don't remember exact message). In the example listed, there is also a bit in the model section that shows how to set a default object.
Related
Often in my team people forget to map certain fields from an input object to an output object. I wanted to write a library for unit testing, that checks if all properties on an output object have been filled with a value different than the default value, if not, an exception should be thrown. Ofcourse certain properties will need to be able to be excluded.
I noticed that Fluent Assertions can already do this with the .Should().BeEquivalentTo() Graph comparison.
However, I when a property is not present on the input object, I run into some trouble. Given the following objects:
public class Input
{
public int Age{ get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Output
{
public int Age { get; set; }
public string FullName{ get; set; }
public static Output CreateFrom(Input i)
{
return new Output
{
Age = i.Age,
FullName= $"{i.FirstName} {i.LastName}"
};
}
}
When I do the following assertion:
var input = new Input
{
Age = 33,
FirstName = "Foo",
LastName = "Bar"
};
var output = Output.CreateFrom(input);
var fullName = $"{input.FirstName} {input.LastName}";
input.Should().BeEquivalentTo(output,
o => o.Using<string>(i => i.Subject.Should().Be(fullName)).When(
info => info.Path.Contains(nameof(output.FullName)))
);
I get an exception that FullName is not a property on the Input object, which is fair, but I can't use .Excluding(o => o.FullName) in this case because that would skip assertion all togheter.
I could use .Excluding(o => o.FullName), and write a seperate assertion below it as follows:
output.FullName.Should().Be(fullName);
but that doesn't fix the problem I'm trying to solve, I want every property to be mapped, OR have a specific assertion in BeEquivalentTo so people don't forget to write mappings. And they can still forget to write this seperate assertion when they add .Exluding.
The .WithMapping<Input>() extension method will also not work, since you can assign one property on the input, to another property on the output, but doesn't account for the scenario described above.
IS there a way to do this with Fluent Assertions? That would be my preference since it's already included in the project. Are there anylibraries that tackle this specific scenario, or am I going to have to write this myself?
Thanks!
I am trying to write a specific value to a page in ASP.NET Core 6. I found multiple solutions with iterators but I am not able to write a single value from non-iteratable models / instances (no enumerators & lists) to a page.
public class UserViewModel
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
This models purpose is to get filled with values from the Identity Framework.
public UserViewModel umodel { get; set; }
Said model gets instanced, filled without any problems - it holds values (checked via console) in page.cshtml.cs:
var user = await _userManager.FindByIdAsync(id);
UserViewModel UserModel = new UserViewModel();
UserModel.UserName = user.UserName;
UserModel.Email = user.Email;
UserModel.Id = user.Id;
Console.WriteLine(UserModel.UserName);
Console.WriteLine(UserModel.Id);
Console.WriteLine(UserModel.Email);
If I try to access it on the corresponding page (page.cshtml) I can only access its name without any problems:
#Html.DisplayNameFor(model => model.umodel.Email)
When I want to access its content there is no value on the page.
#Html.DisplayFor(model => model.umodel.Email)
How can I access the values in this model on a razor page? All the solutions I found based on some kind of iterator and therefore models that had some kind of enumerator or where instanced and filled as a list.
From the code you posted, you aren't populating the page's UserViewModel property. You instantiated a different UserViewModel instance. You wrote the values of that to the Console, but the actual model property (umodel) has not been populated.
Try this in the OnGet method:
var user = await _userManager.FindByIdAsync(id);
umodel.UserName = user.UserName;
umodel.Email = user.Email;
umodel.Id = user.Id;
When rendering property values, you don't need the DisplayFor helper (unless you are using display templates). You just need to prefix the property with #:
#Model.umodel.UserName
I figured it out. There hast to be an instance of the model / class but in a specific way and naming. See following example:
Model:
public class IdentityUserModel
{
public string Id { get; set; }
public string ?UserName { get; set; }
public string ?Email { get; set; }
}
Reference to model in the Main class of the Page (page.cshtml.cs):
public IdentityUserModel IUserModel { get; set; }
Then the important part in the OnGet/OnGetAsync function(?) (page.cshtml.cs):
IUserModel = new(); // <-- instance
var user = [whatever...]
IUserModel.UserName = user.UserName;
IUserModel.Email = user.Email;
IUserModel.Id = user.Id;
Then to write on the page.cshtml:
#Model.IUserModel.Id
My understanding is that there has to be an instance of the class in die page context with exactly the same name (therefore = new() without instance name). I may have been blind but reading throug microsofts learn pages again this is was not clear at all to me.
Thanks to Mike Brind for sending me in the right direction with his input.
I have a view-model like this:
public class U1MyProfile1ViewModel : U1Profile
{
public List<SelectListItem> CountryList { get; set; }
}
Thinking that I want the model accessible to the view, plus a some extra fields that aren't really part of the model, such as a drop down list of countries.
Then in the controller I try to "pass the model over to the view-model"
var myProfile = await _mainDbContext.U1Profiles
.AsNoTracking()
.FirstOrDefaultAsync(i => i.SiteUserId == mySiteUserId);
U1MyProfile1ViewModel myProfileViewModel = (U1MyProfile1ViewModel)myProfile;
this compiles, but I get a runtime error of:
InvalidCastException: Unable to cast object of type 'WebApp.Models.U1Profile' to type 'WebApp.ViewModels.U1MyProfile1ViewModel'.
Any ideas on how to do this easily?
Something simpler than assigning the model to the view-model field by field.
Set your View model like follow:
View modal
public class U1MyProfile1ViewModel
{
public List<SelectListItem> CountryList { get; set; }
public U1Profile U1Profile{get;set;}
public string othervariable{get;set;}
}
Controller
var myProfile = await _mainDbContext.U1Profiles
.AsNoTracking()
.FirstOrDefaultAsync(i => i.SiteUserId == mySiteUserId);
U1MyProfile1ViewModel myProfileViewModel = new U1MyProfile1ViewModel;
U1MyProfile1ViewModel.U1Profile=myProfile;
U1MyProfile1ViewModel.CountryList=yourcountrylist;
And finally just passed your viewmodal to View and you get your result.
For better understanding just see below link:
Link1
Link2
I have a simple class below that I am trying to use to display the Content string in the Editor Kendo Control. I am having issues binding the Property to the Editor. How can I bind the Content String to the Kendo UI Web/MVC Editor using Razor?
public class Details
{
public int TextId { get; set; }
public string Content { get; set; }
}
public List<Details> TextDetails
{
get
{
return mDetails;
}
}
#model MyApp.MyModels.ContentModel
#{
ViewBag.Title = "EditorContent";
}
<h2>Stuff To Display</h2>
#(Html.Kendo().Editor()
.Name("editor")
.Value(Model.TextDetails.Content)
//I thought I could just bind to the property.... How can I show the Content in the Editor?
)
You should do: Model.TextDetails.First().Content, Otherwise everything is fine. As you know Value() requires just a string value and renders as html content, providing appropriate model property (string) shouldn't hurt the editor.
I have a record structure where I have a parent record with many children records. On the same page I will have a couple queries to get all the children.
A later query I will get a record set when I expand it it shows "Proxy". That is fine an all for getting data from the record since everything is generally there. Only problem I have is when I go to grab the record "ID" it is always "0" since it is proxy. This makes it pretty tough when building a dropdown list where I use the record ID as the "selected value". What makes this worse is it is random. So out of a list of 5 items 2 of them will have an ID of "0" because they are proxy.
I can use evict to force it to load at times. However when I am needing lazy load (For Grids) the evict is bad since it kills the lazy load and I can't display the grid contents on the fly.
I am using the following to start my session:
ISession session = FluentSessionManager.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
I even use ".SetFetchMode("MyTable", Eager)" within my queries and it still shows "Proxy".
Proxy is fine, but I need the record ID. Anyone else run into this and have a simple fix?
I would greatly appreciate some help on this.
Thanks.
Per request, here is the query I am running that will result in Patients.Children having an ID of "0" because it is showing up as "Proxy":
public IList<Patients> GetAllPatients()
{
return FluentSessionManager.GetSession()
.CreateCriteria<Patients>()
.Add(Expression.Eq("IsDeleted", false))
.SetFetchMode("Children", Eager)
.List<Patients>();
}
I have found the silver bullet that fixes the proxy issue where you loose your record id!
I was using ClearCache to take care of the problem. That worked just fine for the first couple layers in the record structure. However when you have a scenario of Parient.Child.AnotherLevel.OneMoreLevel.DownOneMore that would not fix the 4th and 5th levels. This method I came up with does. I also did find it mostly presented itself when I would have one to many followed by many to one mapping. So here is the answer to everyone else out there that is running into the same problem.
Domain Structure:
public class Parent : DomainBase<int>
{
public virtual int ID { get { return base.ID2; } set { base.ID2 = value; } }
public virtual string Name { get; set; }
....
}
DomainBase:
public abstract class DomainBase<Y>, IDomainBase<Y>
{
public virtual Y ID //Everything has an identity Key.
{
get;
set;
}
protected internal virtual Y ID2 // Real identity Key
{
get
{
Y myID = this.ID;
if (typeof(Y).ToString() == "System.Int32")
{
if (int.Parse(this.ID.ToString()) == 0)
{
myID = ReadOnlyID;
}
}
return myID;
}
set
{
this.ID = value;
this.ReadOnlyID = value;
}
}
protected internal virtual Y ReadOnlyID { get; set; } // Real identity Key
}
IDomainBase:
public interface IDomainBase<Y>
{
Y ID { get; set; }
}
Domain Mapping:
public class ParentMap : ClassMap<Parent, int>
{
public ParentMap()
{
Schema("dbo");
Table("Parent");
Id(x => x.ID);
Map(x => x.Name);
....
}
}
ClassMap:
public class ClassMap<TEntityType, TIdType> : FluentNHibernate.Mapping.ClassMap<TEntityType> where TEntityType : DomainBase<TIdType>
{
public ClassMap()
{
Id(x => x.ID, "ID");
Map(x => x.ReadOnlyID, "ID").ReadOnly();
}
}