Why is my class nothing? - asp.net

I have a .NET 2010 project. In it, I create a basic user class. Instantiate it and successfully fill it with data. The entire time it is doing this, if I hover over the class, it says it is nothing, even as it fills its properties. Later on, it hoses me in the UI, even though the property has a value it says the class is nothing.
I DO instatiate the class...
Dim oExtendedUser As New ExtendedUser
and here is the classs definition...
Public Class ExtendedUser
Inherits System.Web.Security.MembershipUser
Public Sub New()
_Role = New Role
End Sub
Public Property ExtendedUserID As Int32
Public Property FirstName As String
Public Property LastName As String
Public Property Phone As String
Public Property UserID As Guid
Public Property Role As Role
Public Property UserName() As String
Public Property Password() As String
Public Property SecurityQuestion() As String
Public Property SecurityAnswer() As String
End Class
I changed the class. I added MyBase.New() but the problem persists. On the UI, here is the code that executes when the button is clicked. Director has, as a proprety, ExtendedUSer
Dim oCase As New BE.Case
Dim oDirector As New BE.Director
oDirector = SessionManager.Director 'the values are here
oCase.Investigator.ExtendedUserID = oDirector.ExtendedUser.ExtendedUserID
And here is the Director...
Public Class Director
Public Sub New()
_ExtendedUser = New ExtendedUser
End Sub
Public Property ID As Int32
Public Property ExtendedUser As ExtendedUser
End Class

You got tricked by the ToString Override.
Your object exists but it overrides the ToString Method : MembershipUser.ToString
To validate this behavior, try it with a simple class :
VB.NET
Public Class Test
Public Property TestString As String
Public Overrides Function ToString() As String
Return Me.TestString
End Function
End Class
C#
public class Test
{
public string TestString { get; set; }
public override string ToString()
{
return this.TestString;
}
}
With this code, the Watch will show you an instanciated Test to Nothing, because ToString value will be Nothing. The object exist, but Visual Studio is using the ToString Method to populate the value field, and at this point it is Nothing.
VB.NET
Public Class Test
Public Property TestString As String = ""
Public Overrides Function ToString() As String
Return Me.TestString
End Function
End Class
C#
public class Test
{
public Test()
{
this.TestString = "";
}
public string TestString { get; set; }
public override string ToString()
{
return this.TestString;
}
}
With this code you'll get an empty string.
To get back to your code, you cannot extend the MembershipUser so simply, you have to follow this guideline : How to: Implement a Custom Membership User. As many things won't work with your actual extension (For example, your username shadowing the base one).
See this question as well. There are easier ways to extend your user "entity" than inheritance.

Related

generate dropdown using values from another table in asp.net. vb mvc 4

I have created model class and controller related to a database table and want to populate a dropdown list from another table. my model and controller code is below:-
Imports System.Data.Entity
Namespace employee1
Public Class EmployeeController
Inherits System.Web.Mvc.Controller
Private db As New EmployeeDBContext
'
' GET: /Employee/
Function Index(ByVal sortOrder As String) As ActionResult
ViewBag.LastNameSortParm = If(String.IsNullOrEmpty(sortOrder), "LastName_desc", String.Empty)
Dim Employee = From e In db.Employee Select e
Select Case sortOrder
Case "LastName_desc"
Employee = Employee.OrderByDescending(Function(e) e.LastName)
Case Else
Employee = Employee.OrderBy(Function(e) e.LastName)
End Select
Return View(Employee.ToList())
End Function
'
' GET: /Employee/Details/5
Function Details(Optional ByVal id As Integer = Nothing) As ActionResult
Dim employeemodel As EmployeeModel = db.Employee.Find(id)
If IsNothing(employeemodel) Then
Return HttpNotFound()
End If
Return View(employeemodel)
End Function
'
' GET: /Employee/Create
Function Create() As ActionResult
Return View()
End Function
and this is my model
Imports System.Data.Entity
Public Class EmployeeModel
Public Property ID() As Integer
Public Property CompanyCode() As String
Public Property FirstName() As String
Public Property LastName() As String
Public Property DeptNum() As String
Public Property Status() As Char
Public Property txtCity() As String
Public Property txtState() As String
Public Property txtZip() As String
Public Property txtPhone() As String
Public Property txtPhoneExt() As String
Public Property LastReviewDate() As Date
Public Property HireDate() As Date
End Class
Public Class EmployeeDBContext
Inherits DbContext
Public Property Employee() As DbSet(Of EmployeeModel)
End Class
I want a dropdown list in create view for status from another table named IDStatus view is like
#Using Html.BeginForm()
#Html.ValidationSummary(True)
#<fieldset>
<legend>EmployeeModel</legend>
<div class="editor-label">
#Html.LabelFor(Function(model) model.CompanyCode)
</div>
<div class="editor-field">
#Html.EditorFor(Function(model) model.CompanyCode)
#Html.ValidationMessageFor
</div>
<!-- how do i use dropdown list here which is from different table?-->
</fieldset>
End Using
Either you can add one more property as a collection of the same model, or you can fill that collection in a ViewBage and use it the same at your view.
At Controller
ViewBag.DropDownCollection = "Collection"
At View
#Html.DropDownList("dropDownName",ViewBag.DropDownCollection)
Fiddle
create viewmodel and pass both table properties in that
public class viewmodel
{
public table1 Table1{get;set;} //return your first table properties here
public table2 Table2{get;set;} //return your second table properties here
}
In view
#htnl.dropdownlistfor(m=>m.Table2.propertyname,-----)`enter code here`

Entity Framework - Insert a many-to-many relationship from a FormView

I have two entities linked with an association entity. In code I can easily insert one, or all of these at once. But, on the front end, I am using FormViews to allow the user to enter data. When I insert an address, how do I let it know to insert a facility at the same time, unless I have the facility and the address on the same formview?
Public Class facility
<Key()> _
Public Property facility_id As Integer
Public Property facility_present_use As String
Public Property facility_prior_use As String
Public Property facility_occupied As Boolean
Public Property facility_size As Double
Public Property facility_floors As Integer
Public Property facility_age As Integer
Public Property facility_single_residence As Boolean
Public Property facility_number_of_units As Integer
Public Overridable Property facility_address As ICollection(Of facility_address) = New HashSet(Of facility_address)
End Class
Public Class address
<Key()> _
Public Property address_id As Integer
Public Property address_name As String
Public Property address_address_1 As String
Public Property address_address_2 As String
Public Property address_city As String
Public Property address_state As Integer?
Public Property address_zip As String
Public Property address_contact_first_name As String
Public Property address_contact_last_name As String
Public Property address_phone_area As String
Public Property address_phone As String
Public Overridable Property lu_state As lu_state
Public Overridable Property facility_address As ICollection(Of facility_address) = New HashSet(Of facility_address)
End Class
Public Class facility_address
<Key()> _
Public Property facility_address_id As Integer
Public Property address_type As Integer
Public Property facility_id As Integer
Public Property address_id As Integer
Public Overridable Property lu_address_type As lu_address_type
Public Overridable Property facility As facility
Public Overridable Property address As address
End Class

aspnet webapi bind query string to object

<HttpGet()>
Public Function Search(<FromUri()> ByVal name As Name) As HttpResponseMessage
// get params from complex type
// or check for model validation
name.firstName;
name.lastName;
End Function
Public Class Name
<Required()>
Public firstName As String
<Required()>
Public lastName As String
End Class
/api/abc/search?firstName=jack&lastName=daniels
I am trying to send a comlex type as a query parameter but name is always null even though I am using fromUri attribute. What am I missing?
EDIT: I am also using Required() attribute from System.ComponentModel.DataAnnotations .
I found the problem. I was missing the Property keywords on my fields.
Public Class Name
<Required()>
Public firstName As String
<Required()>
Public lastName As String
End Class
So, it worked with the following change.
Public Class Name
<Required()>
Public Property firstName As String
<Required()>
Public Property lastName As String
End Class
The problem solved. I think, without properties, the class does not expose its fields, so I cant read them from uri.

Updating just a subset of fields in a row

I'm learning asp.net MVC. Using the Code First model, where you create your class, and then use the EF to manage all database interactions.
Is there anyway of only requesting some of the fields from a given table using this method, and only updating those fields?
My whole class is:
Public Class Employee
Public Property ID() As Integer
<DisplayName("Staff Name")>
<Required()>
Public Property StaffName() As String
<DisplayName("Location")>
<Required()>
Public Property Location() As String
<Required()>
<DisplayName("Team Leader")>
Public Property teamleader() As String
Public Property ScoreCardM1() As Integer
Public Property ScoreCardM1Notes() As String
Public Property ScoreCardM2() As Integer
Public Property ScoreCardM2Notes() As String
Public Property ScoreCardM3() As Integer
Public Property ScoreCardM3Notes() As String
Public Property ScoreCardM4() As Integer
Public Property ScoreCardM4Notes() As String
Public Property ScoreCardM5() As Integer
Public Property ScoreCardM5Notes() As String
Public Property ScoreCardM6() As Integer
Public Property ScoreCardM6Notes() As String
Public Property ScoreCardTotal() As Integer
Public Property ScoreCardTotalNotes() As String
Public Property ScoreCardM7() As Integer
Public Property ScoreCardM7Notes() As String
Public Property ScoreCardM8() As Integer
Public Property ScoreCardM8Notes() As String
Public Property ScoreCardM9() As Integer
Public Property ScoreCardM9Notes() As String
Public Property ScoreCardQ3Total() As Integer
Public Property ScoreCardQ3TotalNotes() As String
Public Property ScoreCardM10() As Integer
Public Property ScoreCardM10Notes() As String
Public Property ScoreCardM11() As Integer
Public Property ScoreCardM11Notes() As String
Public Property ScoreCardM12() As Integer
Public Property ScoreCardM12Notes() As String
Public Property ScoreCardQ4Total() As Integer
Public Property ScoreCardQ4TotalNotes() As String
Public Property GeneralNotes() As String
End Class
However, I only want to display and edit one month at a time:
Public Class Employee
Public Property ID() As Integer
<DisplayName("Staff Name")>
<Required()>
Public Property StaffName() As String
Public Property ScoreCardM1() As Integer
Public Property ScoreCardM1Notes() As String
End Class
How do I best achieve this? Do I setup another 12 classes, with just one month contained within each, or is there a best practice way of updating a subset of fields within a database row, without affecting the others?
Thanks for any help,
Mark
further to my comment above.... you can set up your classes as follow:
Employee Class:
Public Class Employee
Public Property EmployeeID() As Integer
<DisplayName("Staff Name")>
<Required()>
Public Property StaffName() As String
<DisplayName("Location")>
<Required()>
Public Property Location() As String
<Required()>
<DisplayName("Team Leader")>
Public Property teamleader() As String
Public virtual Property reports() As ICollection<Of MonthlyRports> // not sure if the syntax is right (haven't worked in VB)
End Class
MonthlyReport Class
Public Class Employee
Public Property MonthlyReportID() As Integer // primary key
Public Property EmployeeID() As Integer // foreign key. who this report belongs to
Public Property Month As String // report for month ...
Public Property ScoreCard() As Integer
Public Property ScoreCardNotes() As String
End Class

What is the best method for attaching a single key/value pair attribute to an enumeration?

I'm trying to figure out what the best method is for attaching a single key/value pair attribute to an enumeration where the key is my MerchantId and the value is the corresponding TransactionKey.
What I currently do is put a comma delimited string into a StringValueAttribute class:
Public Enum Merchants
<StringValue("coke,faj80785hq+faf=-1=-jfa+">
Coke = 0
<StringValue("pepsi,adfji=-901jnas++fdj98ua")>
Pepsi = 1
<StringValue("drpepper,jk878-=+9kdkdja0=a=f--daj")>
DrPepper = 2
End Enum
Public Property Merchant As Merchants
I pull out the key or MerchantId by calling .GetStringValue().Split(","c)(0):
Public ReadOnly Property MerchantId() As String
Get
Return Merchant.GetStringValue().Split(","c)(0)
End Get
End Property
I pull out the value or TransactionKey by calling .GetStringValue().Split(","c)(1):
Public ReadOnly Property TransactionKey() As String
Get
Return Merchant.GetStringValue().Split(","c)(1)
End Get
End Property
Is this the most efficient way to do this? Instead of StringValueAttribute, what about creating an attribute using a Dictionary(Of String, String) since it is a key/value pair list? Or String Array or List? Maybe something in LINQ? Or is it simply already efficient as it can be?
You can use the following custom attribute and extension methods to get the values. Some things to note:
It's in C#, hope that's ok :)
The extension methods class caches the MerchantIds and TransactionIds in static scope, so should be pretty efficient.
You get the MerchantId by calling (e.g.) Merchants.Coke.GetMerchantId();.
You get the TransactionId by calling (e.g.) Merchants.Coke.GetTransactionId();.
Also, the extension methods don't bother checking that the Merchants value passed to them is valid, so you could break it by calling ((Merchants)76282).GetMerchantId().
[AttributeUsage(AttributeTargets.Field)]
public class MerchantDataAttribute : Attribute
{
public MerchantDataAttribute(string merchantId, string transactionId)
{
this.MerchantId = merchantId;
this.TransactionId = transactionId;
}
public string MerchantId
{
get;
private set;
}
public string TransactionId
{
get;
private set;
}
}
public static class MerchantsExtensions
{
private static readonly Dictionary<Merchants, MerchantDataAttribute>
_merchantsCache = CacheMerchantsCache();
public static string GetMerchantId(this Merchants merchants)
{
return _merchantsCache[merchants].MerchantId;
}
public static string GetTransactionId(this Merchants merchants)
{
return _merchantsCache[merchants].TransactionId;
}
private static Dictionary<Merchants, MerchantDataAttribute> CacheMerchantsCache()
{
return Enum.GetValues(typeof(Merchants))
.Cast<Merchants>()
.Select(m => new
{
Merchant = m,
MerchantAttribute = GetMerchantAttribute(m)
})
.ToDictionary(m => m.Merchant, m => m.MerchantAttribute);
}
private static MerchantDataAttribute GetMerchantAttribute(Merchants merchant)
{
return typeof(Merchants)
.GetMember(merchant.ToString())
.First()
.GetCustomAttributes(typeof(MerchantDataAttribute), inherit: false)
.Cast<MerchantDataAttribute>()
.First();
}
}
I would suggest creating your own attribute class which takes both values in a type-safe manner and names them appropriately. Or, if not every item will have both values, create two separate attributes, one for each value.
Or better yet, don't use an Enum at all. Create your own class that takes all three values in the constructor and then create a class with shared properties for each item, as such:
Public Class Merchants
Public Shared ReadOnly Property Coke() As Merchant
Get
Return _coke
End Get
End Property
Private Shared _coke = New Merchant(0, "Coke", "faj80785hq+faf=-1=-jfa+")
...
End Class
For any future visitors, I thought I'd post the VB version of the answer, since that's what I tagged the question with. Also, I had to do things slightly different due to VB requiring extensions to be inside of a Module.
Here is the Module:
(I used a lot of line continuation for easier readability. Also, for the sake of readability in this example I imported SomeClass so that I didn't have to type out that NameSpace)
Imports SomeClass
Module MerchantsExtensions
Private ReadOnly MerchantsCache _
As Dictionary(Of Merchants, MerchantDataAttribute) _
= CacheMerchantsCache()
Private Function CacheMerchantsCache() _
As Dictionary(Of Merchants, MerchantDataAttribute)
Return [Enum].GetValues(GetType(Merchants)) _
.Cast(Of Merchants)() _
.Select(Function(m) New With
{
.Merchant = m,
.MerchantAttribute = GetMerchantAttribute(m)
}) _
.ToDictionary(Function(m) m.Merchant, _
Function(m) m.MerchantAttribute)
End Function
Private Function GetMerchantAttribute(merchant As Merchants) _
As MerchantDataAttribute
Return GetType(Merchants) _
.GetMember(merchant.ToString()) _
.First() _
.GetCustomAttributes(GetType(MerchantDataAttribute), _
inherit:=False) _
.Cast(Of MerchantDataAttribute)() _
.First()
End Function
<Runtime.CompilerServices.Extension()>
Public Function GetMerchantId(merchants As Merchants) As String
Return MerchantsCache(merchants).Id
End Function
<Runtime.CompilerServices.Extension()>
Public Function GetTransactionKey(merchants As Merchants) As String
Return MerchantsCache(merchants).TransactionKey
End Function
End Module
Here is the implementation of the extension methods in a class I named SomeClass for this example:
Public Class SomeClass
Public Enum Merchants
<MerchantData("coke", "faj80785hq+faf=-1=-jfa+")>
Coke = 0
<MerchantData("pepsi","adfji=-901jnas++fdj98ua")>
Pepsi = 1
<MerchantData("drpepper","jk878-=+9kdkdja0=a=f--daj")>
DrPepper = 2
End Enum
<AttributeUsage(AttributeTargets.Field)>
Public Class MerchantDataAttribute : Inherits Attribute
Public Sub New(merchantId As String, transactionKey As String)
_Id = merchantId
_TransactionKey = transactionKey
End Sub
Public Property Id() As String
Public Property TransactionKey() As String
End Class
End Class

Resources