Click here to Skip to main content
15,893,668 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In MVC, I'm struggling get the functionality that I used to get from a ASP.net webforms usercontrol. I'd like a reusable chunk of code that contains a bunch of inputs but will ultimately return a single value to the model. For the sake of a simple example lets say i have the following viewmodel.
C#
public class Person 
{
   public string Name { get;set;}
   public DateTime DateOfBirth { get; set;}
   public DateTime DateOfDeath { get; set;}
}

I'd like to create the input controls that make up the DateTime fields to be reusable, so I guess I put them in a PartialView, _myDateControl.cshtml, as follows:
HTML
<!-- Don't know how to make the IDs unique every time i call this partialview on the same page -->
<label>Enter the year: <input type="text" name="year" /></label>
<label>Enter the month: <input type="text" name="month" /></label>
<label>Enter the day: <input type="text" name="day" /></label>

Then a view something like
HTML
@model Person
@using (Html.BeginForm())
{
   @Html.EditorFor(m => m.Name)
   @Html.Partial("_MyDateControl") @*How do i map this to DateOfBirth *@
   @Html.Partial("_MyDateControl") @*How do i map this to DateOfDeath *@
   <input type="submit" value="Save Person" />
}


Am I going about this the right way? Or should I be looking at custom Html Helpers?

What I have tried:

All the examples of PartialViews I see, just seem to have basic html tags and not any input tags that will be part of a form.
Posted
Updated 20-Jul-17 21:20pm

Here is an example.

Model: YourDummyModel is the application Object/Model, YourDummyControl is to hold the control name/id and value
C#
public class YourDummyModel
{
    public string FieldOne { get; set; }
    public string FieldTwo { get; set; }
}

public class YourDummyControl
{
    public string ControlName { get; set; }
    public string ControlValue { get; set; }
}


Controller : On page load, populate the Model with some dummy data. On Postback, the application should return the value in the Textbox to the controller
C#
public ActionResult TestPartialView()
{
    var model = new YourDummyModel();
    model.FieldOne = "Your Field 1";
    model.FieldTwo = "Your Field 2";

    return View(model);
}

[HttpPost]
[AllowAnonymous]
public ActionResult TestPartialView(YourDummyModel model)
{
    return View(model);
}


_MySharedView.cshtml : This is the shared view/ user control
HTML
@model WebApplication1.Models.YourDummyControl
<div class="form-group">
    @Html.Label(Model.ControlName, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBox(Model.ControlName , Model.ControlValue, new { @class = "form-control" })
    </div>
</div>


YourView : This is the page view, in reality, your page might have more elements. The page will call the Html.RenderPartial method to load the partial view and passing in the control name and control value from the Model class.
HTML
@model WebApplication1.Models.YourDummyModel
<h2>TestPartialView</h2>
@using (Html.BeginForm())
{
    Html.RenderPartial("~/Views/shared/_MySharedView.cshtml",
                new WebApplication1.Models.YourDummyControl { ControlName = "FieldOne", ControlValue = Model .FieldOne  });

    Html.RenderPartial("~/Views/shared/_MySharedView.cshtml",
               new WebApplication1.Models.YourDummyControl { ControlName = "FieldTwo", ControlValue = Model.FieldTwo  });
    <input type="submit" value="Create" class="btn btn-default" />
}


More complicated control:
ASP.NET MVC3 Slideshow Control using jQuery and XML[^]

More reading:
Generate unique ids for Html Elements of partial view called inside foreach statement. | The ASP.NET Forums[^]

Hope this help. If not ask.
 
Share this answer
 
Comments
Karthik_Mahalingam 20-Jul-17 23:49pm    
5
Bryian Tan 21-Jul-17 10:23am    
Thank you Sir!
Thank you very much Brian. You put me on the right track with the DummyControl class. My real world user control needed to have about 12 inputs on it, so having a control name for each was a bit messy. Ultimately I was looking for the HtmlFieldPrefix property to solve the unique input IDs problem. Here's the simple example solution I ended up with:

C#
// data model
public class Person
{
    public string Name { get; set; }
    public DateTimeControl DateOfBirth { get; set; }
    public DateTimeControl DateOfDeath { get; set; }
}
// model to hold UserControl values
public class DateTimeControl
{
    [Display(Name = "Day: ")]
    public string Day { get; set; }
    [Display(Name = "Month: ")]
    public string Month { get; set; }
    [Display(Name = "Year: ")]
    public string Year { get; set; }
}


And the partial view as follows:
HTML
@model Models.DateTimeControl
<div class="form-group">
    @Html.LabelFor(m => m.Day)
    @Html.EditorFor(m => m.Day, new { @class = "form-control" })
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Month)
    @Html.EditorFor(m => m.Month, new { @class = "form-control" })
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Year)
    @Html.EditorFor(m => m.Year, new { @class = "form-control" })
</div>

Then I can use the partial view multiple times in the same view, overcoming the unique IDs with the HtmlFieldPrefix property.
HTML
<div class="form-group">
  @Html.LabelFor(m => m.Name)
  @Html.EditorFor(m => m.Name, new { @class = "form-control" })
</div>
  @Html.Partial("_DateTimeInput", Model.DateOfBirth, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "DateOfBirth" } })
  @Html.Partial("_DateTimeInput", Model.DateOfDeath, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "DateOfDeath" } })


So that the generated HTML is:
HTML
                    <div class="form-group">
    <label for="DateOfBirth_Day">Day: </label>
    <input class="text-box single-line" id="DateOfBirth_Day" name="DateOfBirth.Day" type="text" value="" />
</div>
<div class="form-group">
    <label for="DateOfBirth_Month">Month: </label>
    <input class="text-box single-line" id="DateOfBirth_Month" name="DateOfBirth.Month" type="text" value="" />
</div>
<div class="form-group">
    <label for="DateOfBirth_Year">Year: </label>
    <input class="text-box single-line" id="DateOfBirth_Year" name="DateOfBirth.Year" type="text" value="" />
</div>

                    <div class="form-group">
    <label for="DateOfDeath_Day">Day: </label>
    <input class="text-box single-line" id="DateOfDeath_Day" name="DateOfDeath.Day" type="text" value="" />
</div>
<div class="form-group">
    <label for="DateOfDeath_Month">Month: </label>
    <input class="text-box single-line" id="DateOfDeath_Month" name="DateOfDeath.Month" type="text" value="" />
</div>
<div class="form-group">
    <label for="DateOfDeath_Year">Year: </label>
    <input class="text-box single-line" id="DateOfDeath_Year" name="DateOfDeath.Year" type="text" value="" />
</div>

When mixed with additional inputs in the outer View, the entire model is populated and sent to the controller as expected when the user hits the submit button.
 
Share this answer
 
Comments
Bryian Tan 21-Jul-17 10:23am    
I'm glad you got it figured out. Good job!!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900