Binding custom property in Entity Framework - webforms

I have an employee entity in my EF model. I then added a class to the project to add a custom property
public partial class Employee
{
public string Name
{
get { return string.Format("{0} {1}", this.FirstName, this.LastName); }
}
}
On a aspx form (inside a FormView), I want to bind a DropDownList to the employee collection:
<asp:Label runat="server" AssociatedControlID="ddlManagerId"
Text="ManagerId" />
<asp:DropDownList ID="ddlManagerId" runat="server"
DataSourceID="edsManagerId"
DataValueField="Id"
DataTextField="Name"
AppendDataBoundItems="true"
SelectedValue='<%# Bind("ManagerId") %>'>
<asp:ListItem Text="-- Select --" Value="0" />
</asp:DropDownList>
<asp:EntityDataSource ID="edsManagerId" runat="server"
ConnectionString="name=Entities"
DefaultContainerName="Entities"
EntitySetName="Employees"
EntityTypeFilter="Employee"
EnableFlattening="true">
</asp:EntityDataSource>
Unfortunately, when I fire up the page, I get an error:
DataBinding: 'System.Web.UI.WebControls.EntityDataSourceWrapper' does not contain a property with the name 'Name'.
Any ideas what I'm doing wrong?

After much searching I discovered that that the EntityDataSource does not support custom properties in the partial classes. It only returns the entity that is in the model.

As per this article:
The issue is that we’re using the EntityDataSourceWrapper and not our actual entity. The solution? Stop using the wrapper!
Disable flattening, like this:
<asp:EntityDataSource
...
EnableFlattening="False"
...
</asp:EntityDataSource>
More information on Flattening is here.

Could you verify that both your partial Employee classes are in the same namespace?

Related

Is it possible to get a SqlDataSource parameter from the ViewState in asp.net web forms?

I have a SqlDataSource defined in my aspx file that I use to call a StoredProcedure. It takes a hiddenField as its control parameter.
<asp:HiddenField ID="input" runat="server" />
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="input" Name="input" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
Is there a way I can grab that parameter from the ViewState instead? Preferably while keeping the datasource definition in the aspx file.
The solution in your case is very easy. Just create your own class inherit it from Parameter and override Evaluate method.
[DefaultProperty("ViewStateKey")]
public class ViewStateParameter : Parameter
{
public string ViewStateKey
{
get
{
return (string)ViewState["ViewStateKey"] ?? string.Empty;
}
set
{
if (ViewStateKey == value)
return;
ViewState["ViewStateKey"] = value;
OnParameterChanged();
}
}
protected override object Evaluate(HttpContext context, Control control)
{
if (control == null || string.IsNullOrEmpty(ViewStateKey))
return null;
return ViewState[ViewStateKey];
}
}
After that you will be able to use your parameter like following (just remember to register it at the top of your page or in web.config):
<asp:SqlDataSource ID="source" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="sp" SelectCommandType="StoredProcedure">
<SelectParameters>
<my:ViewStateParameter Name="input" Type="String" ViewStateKey="input" />
</SelectParameters>
</asp:SqlDataSource>
And your parameter will get its value from viewstate by key input.
I dont feel that the code for ViewStateParameter is of the first class. Maybe you will want to decorate it with more attributes and/or extra parameter checks with assertions.
I have similar problem. I dont want to use hidden fields to bind data source parameters because of security reasons.
I have googled one work-around - use asp:label instead of hidden field (make sure Visible=false). And then your label goes to view state and you can bind label to data source parameters.

MVC3 - Pass back a model from RenderPartial

I have a page in MVC3 with a model of "pageModel".
In this page I have:
#{ Html.RenderPartial("_subPage", Model.subModel); } (Pagemodel.submodel)
In my controller I am doing:
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Results(pagemodel model, string frmAction)
{
}
The page loads fine the first time, but when I postback into the httpPost action, model.submodel is always null.
My question is, how do I return an updated model from the RenderPartial (if at all). I can get my model INTO the partial, but not back!
The problem with partials is that they do not preserve the navigational context. This means that any input fields that you might have put inside this partial will have incorrect names and the default model binder will not be able to retrieve the values back when you POST. Your HTML will look like this:
<input type="text" name="Prop1" value="property 1 value" />
<input type="text" name="Prop2" value="property 2 value" />
whereas the correct is:
<input type="text" name="subModel.Prop1" value="property 1 value" />
<input type="text" name="subModel.Prop2" value="property 2 value" />
In order to achieve this correct markup I would recommend you using editor templates.
So you replace:
#{ Html.RenderPartial("_subPage", Model.subModel); }
with:
#Html.EditorFor(x => x.subModel)
and then you move your _subPage.cshtml partial into ~/Views/Shared/EditorTemplates/SubModelType.cshtml where SubModelType is the type of the subModel property:
#model SubModelType
#Html.EditorFor(x => x.Prop1)
#Html.EditorFor(x => x.Prop2)
Now when you look at the generated HTML the corresponding input field names should be prefixed with subModel and inside the POST controller action the model.subModel property will this time be properly initialized and populated from the values that were entered by the user in the input fields.
you'll need to change your partialview to accept the top level model, i.e:
#{ Html.RenderPartial("_subPage", Model); }
which would then render your properties in the partialview with the correct property names i.e. :
<input type="text" name="subModel.MyProperty" value="somevalue" />
It would also mean that your returned model in the HttpPost action will have to correct navigational relationship intact.
this is just one of those caveats related to viewmodels and hierarchies. Oh, btw, in mvc3, you don't need the verbose [AcceptVerbs(HttpVerbs.Post)] for posts. You can simply use [HttpPost]
You can also perform the following.
#Html.RenderPartial(
"_subPage",
Model.subModel,
new ViewDataDictionary
{
TemplateInfo = new TemplateInfo
{
HtmlFieldPrefix = "subModel"
}
});
Your partial view will remain as is, using the #model SubModel

MVC Dropdownlist to Telerik MVC Dropdowlist

I am trying to convert the following asp dropdowlist to telerik mvc dropdownlist.
I am using SQL stored procedures to popluate the list.
<asp:DropDownList ID="userName" name="userName" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FullName" DataValueField="UserName">
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:HHNConnectionString %>"
SelectCommand="GetUserName" SelectCommandType="StoredProcedure"></asp:SqlDataSource>
Thanks in advance.
The combobox is what you're looking for I assume. Are you asking how to rewrite your control with the Telerik control?
Well, first you don't specify the stored procedure with the MVC control. You'll want to pass that in on your viewmodel. Whatever you're using for database connectivity will be responsible for calling the stored procedure.
// Controller method
public ActionResult MyAction()
{
// Pull user names from the database
var users = _repository.FindAllUsers().Select(u => u.UserName);
return View(users);
}
Then your view would look something like this:
#model IEnumerable<string>
#(Html.Telerik().DropDownList()
.Name("userName")
)
If you have a pre-selected user name, then you'll want to create an actual viewmodel class:
public MyViewModel
{
public string UserName { get; set;}
public IEnumerable<string> UserList { get; set; }
}
Then you can use the #(Html.Telerik().DropDownListFor(m => m.UserName)) method.

Binding list of Dates using specific culture in asp.net mvc 3 fails

i have this scenario where i need to accept three meeting schedules , below are the details
meeting Schedule model
public class MeetingSchedule
{
public DateTime Date { get; set; }
}
Form looks like
<form action="#Url.Action("Schedule")" method="post" >
<input type="text" name="meetingSchedules[1].Date" id="schedule2" class="datepicker" />
<input type="text" name="meetingSchedules[2].Date" id="schedule3" class="datepicker" />
</form>
and Action
[HttpPost]
public ActionResult Schedule(List<MeetingSchedule> meetingSchedules)
{}
i set the culture
<system.web>
<globalization uiCulture="en-GB" culture="en-GB" />
</system.web>
Still could not bind Date of format "dd/MM/yyyy", ex: if i choose any one date as 26/10/2011 , the model binder could not bind it , instead show default DateTime Value.
Please help me with this
Thanks
I ran into same issue and found out the problem is with the code.
If you think of action as a plain method, the model binder kicks in when the action method is invoked, prior to this if you have set the culture info then you are all set.
In the constructor add following code:
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
Now try again, the model binder should now be able to recognize the date in dd/MM/yyyy format.

ASP.Net MVC3 Parent Child Model Binding

I have a partial template that uses a User object as a model. The user has a collection of Accounts. On this partial template I have a loop as follows. The _Account partial template is bound to the Account class
#foreach (var item in Model.Accounts)
{
<tr>
<td colspan="6">
<div>
#Html.Partial("_Account", item)
</div>
</td>
</tr>
}
In my controller method I initially tried
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user, string actionType)
But the User.Accounts collection is empty. Then I tried this. Still the Accounts collection is empty.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user,
[Bind(Prefix="User.Accounts")]
FixupCollection<Account> Accounts,
string actionType)
Can I use the default Modelbinder implementation to achieve this or do I need to do anything different?
Yep, you can use the default model binder. You just need to name your fields correctly. So you need your loop to output something like this:
...
<input type="text" name="user.Accounts[0].SomeTextField" />
<input type="text" name="user.Accounts[0].SomeOtherTextField" />
...
<input type="text" name="user.Accounts[1].SomeTextField" />
<input type="text" name="user.Accounts[1].SomeOtherTextField" />
...
If you need to add/remove accounts, the hardcoded indexes get a little trickier. You could re-assign the names using javascript before postback. But it's all possible. This question gives more detail on model binding:
ASP.NET MVC: Binding a Complex Type to a Select
Use Editor Templates instead of a partial view - no need to hard code your indexes as the template will automagically index all your objects correctly, even when you add and remove Accounts. See my answer to this question:
Pass values from multiple partial views
Small write up on Editor Templates here:
codenodes.wordpress.com - MVC3 Editor Templates

Resources