0

I have two classes that contain data only (Settings and Credentials). I don't know how I should call these classes so bear with me.

Example of data classes.

class Settings
{

        public string Host { get; set; }
        public int Port { get; set; }

}


class Credentials
{

        public string UserName { get; set; }
        public string Password { get; set; }

}

I want to create a new object containing these two data classes using a MVC controller action.

Example of object class.

class Object
{
        private readonly Settings _settings;
        private readonly Credentials _credentials;

        public Object(Settings settings, Credentials credentials)
        {
            _settings = settings;
            _credentials = credentials;
        }
}

Example for what I'm trying to do.

public class HomeController : Controller
{
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Create(Settings settings, Credentials credentials)
        {
            new Object(settings, credentials);

            return View(Index());
        }
}

My question how can I achieve this is a nice manner? Without having to put every single parameter in the IActionResult Create() method.

And what should my POST form look like?

Thanks.

Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
Typically
  • 41
  • 1
  • 8
  • You want to pass both models at the same view, right? If I'm right, you should create another class which contains both models and pass it to view instead. – Tetsuya Yamamoto Oct 16 '18 at 08:05
  • @TetsuyaYamamoto Yes, how does this work with POST requests though? – Typically Oct 16 '18 at 08:06
  • You can see how to post multiple models here: https://stackoverflow.com/questions/4764011/multiple-models-in-a-view. The approach should be similar for both Core MVC and previous MVC versions. – Tetsuya Yamamoto Oct 16 '18 at 08:12
  • @TetsuyaYamamoto Okay I read the post but this isn't really what I'm trying to achieve I think. I'm trying to pass two models at the same time in the same form. However creating one big model with the two other models might work but how will it allocate for example the username input from the form to the right model? (Credentials). – Typically Oct 16 '18 at 08:19
  • The usage of single model class that contains both models is due to limitations of `@model` directive in view side. You can create 2 partial views for both `Settings` and `Credentials` separately, use HTML/tag helpers and render them as a single view, then during POST request all values should be received in `Create` action. – Tetsuya Yamamoto Oct 16 '18 at 08:24

1 Answers1

1

You almost got it right. The models I would use:

public class Settings
{
    public string Host { get; set; }
    public int Port { get; set; }

}

public class Credentials
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

class Object
{
    private readonly Settings _settings;
    private readonly Credentials _credentials;

    public Object(Settings settings, Credentials credentials)
    {
        _settings = settings;
        _credentials = credentials;
    }
}

public class ObjectView
{
    public Settings Settings { get; set; }
    public Credentials Credentials { get; set; }
}

Controller actions:

public IActionResult Index()
{
    return View();
}

public IActionResult Create()
{
    return View(new ObjectView());
}

[HttpPost]
public IActionResult Create(ObjectView objectView)
{
    var obj = new Object(objectView.Settings, objectView.Credentials);

    return RedirectToAction("Index");
}

Razor View for Create model:

@model ObjectAsParametersInAction.Models.ObjectView
@{
    ViewBag.Title = "View";
}
<h2>View</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <h4>ObjectView</h4>
        @Html.LabelFor(m => m.Credentials.UserName)
        @Html.EditorFor(m => m.Credentials.UserName)
        @Html.LabelFor(m => m.Credentials.Password)
        @Html.EditorFor(m => m.Credentials.Password)

        @Html.LabelFor(m => m.Settings.Host)
        @Html.EditorFor(m => m.Settings.Host)
        @Html.LabelFor(m => m.Settings.Port)
        @Html.EditorFor(m => m.Settings.Port)
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Posted form data in request will contain parameters, for example:

Credentials.UserName=John&Credentials.Password=Unkown&Settings.Host=127.0.0.1&Settings.Port=80

It all will be model binded to ObjectView public properties in Create post action.

alexqc
  • 547
  • 4
  • 9