Add a dropdown for a field not in the model (asp.n

2019-03-05 06:07发布

问题:

I am using Active Directory Authentication Library to create users and list them. I have a view and controller action to do this.

However please review the MODEL of the view, its a User Entity coming from the API of Azure Active Directory

@model Microsoft.Azure.ActiveDirectory.GraphClient.User
@{
    ViewBag.Title = "Create";
    Layout = "~/Areas/GlobalAdmin/Views/Shared/_LayoutGlobalAdmin.cshtml";
}

<div class="row wrapper border-bottom white-bg page-heading">
    <div class="col-sm-4">
        <h2>Create</h2>
        <ol class="breadcrumb">
            <li>
                @Html.ActionLink("List", "Index")
            </li>
            <li class="active">
                <strong>Create</strong>
            </li>
        </ol>
    </div>
    <div class="col-sm-8">
        <div class="title-action">
            @Html.ActionLink("Back to List", "Index", null, new { @class = "btn btn-primary"})
        </div>
    </div>
</div>


<div class="wrapper wrapper-content animated fadeInRight">
    <div class="row">
        <div class="col-lg-12">
            <div class="ibox float-e-margins">
                <div class="ibox-title">
                    <h5>Crear Usuario</h5>
                </div>
                <div class="ibox-content">

                    @using (Html.BeginForm())
                    {
                        @Html.ValidationSummary(true)

                        <fieldset>
                            <legend>User</legend>
                            <div class="editor-label">
                                @Html.LabelFor(model => model.UserPrincipalName)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.UserPrincipalName)
                                @Html.ValidationMessageFor(model => model.UserPrincipalName)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.AccountEnabled)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.AccountEnabled)
                                @Html.ValidationMessageFor(model => model.AccountEnabled)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.PasswordProfile.Password)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.PasswordProfile.Password)
                                @Html.ValidationMessageFor(model => model.PasswordProfile.Password)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.MailNickname)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.MailNickname)
                                @Html.ValidationMessageFor(model => model.MailNickname)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.DisplayName)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.DisplayName)
                                @Html.ValidationMessageFor(model => model.DisplayName)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.GivenName)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.GivenName)
                                @Html.ValidationMessageFor(model => model.GivenName)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.Surname)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.Surname)
                                @Html.ValidationMessageFor(model => model.Surname)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.JobTitle)
                            </div>
                            <div class="editor-field">
                                @Html.EditorFor(model => model.JobTitle)
                                @Html.ValidationMessageFor(model => model.JobTitle)
                            </div>

                            <div class="editor-label">
                                @Html.LabelFor(model => model.Department)
                            </div>

                            <div class="editor-field">
                                @Html.EditorFor(model => model.Department)
                                @Html.ValidationMessageFor(model => model.Department)
                            </div>

                            <div class="editor-label">
                                @Html.Label("Empresa")
                            </div>
                            @{
                                List<SelectListItem> listItems = new List<SelectListItem>();
                                listItems.Add(new SelectListItem
                                {
                                    Text = "Company1",
                                    Value = "Company1"
                                });
                                listItems.Add(new SelectListItem
                                {
                                    Text = "Company2",
                                    Value = "Company2",
                                    Selected = true
                                });
                                listItems.Add(new SelectListItem
                                {
                                    Text = "Company3",
                                    Value = "Company3"
                                });
                            }
                            <div class="editor-field">
                                @Html.DropDownListFor(model => model.Department)
                            </div>

                            <p>
                                <input type="submit" value="Create" />
                            </p>
                        </fieldset>
                    }


                </div>
            </div>
        </div>
    </div>
 </div>

In Azure Active Directory as in on prem AD, you can add custom properties, these custom properties are called azure active directory schema extensions. They are very well explained here: http://justazure.com/azure-active-directory-part-6-schema-extensions/

However that is not the problem I am concerned.

My Active Directory already has a new extension property called company. And I now the code to set the value of that extension property, check this controller action, the lines TO BE FINISHED

 public async Task<ActionResult> Create(
            [Bind(
                Include =
                    "UserPrincipalName,AccountEnabled,PasswordProfile,MailNickname,DisplayName,GivenName,Surname,JobTitle,Department"
                )] Microsoft.Azure.ActiveDirectory.GraphClient.User user)
        {
            ActiveDirectoryClient client = null;
            try
            {
                client = AuthenticationHelper.GetActiveDirectoryClient();
            }
            catch (Exception e)
            {
                if (Request.QueryString["reauth"] == "True")
                {
                    //
                    // Send an OpenID Connect sign-in request to get a new set of tokens.
                    // If the user still has a valid session with Azure AD, they will not be prompted for their credentials.
                    // The OpenID Connect middleware will return to this controller after the sign-in response has been handled.
                    //
                    HttpContext.GetOwinContext()
                        .Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType);
                }

                //
                // The user needs to re-authorize.  Show them a message to that effect.
                //
                ViewBag.ErrorMessage = "AuthorizationRequired";
                return View();
            }

            try
            {
                await client.Users.AddUserAsync(user);

                //TO BE FINISHED
                user.SetExtendedProperty("Compania", "");
                await user.UpdateAsync();
                Task.WaitAll();

                // Save the extended property value to Azure AD.
                user.GetContext().SaveChanges();
                return RedirectToAction("Index");
            }
            catch (Exception exception)
            {
                ModelState.AddModelError("", exception.Message);
                return View();
            }
        }

Question is:

  1. the DropDownListFor needs a property in the model, but in the User class there is no property so how can I create the dropdownlist?, in my view as you can see there is sample data, I will take care of fixing that with real data from the data source later.

  2. After I fix that how can I get the value of the selected dropdown in the controller?

回答1:

You can always add a key-value pair list property to your view model. And you can extend that list as your users add extended properties to your AD entity. Your list can start as an empty collection when you pass to your view. Then in your view, you iterate through the items in your collection to show each key-value pair in a list type display.

Your controller can have a method that serves a partial view of your key-value pair entry (ie, partial view with two input: one for the property name and one for the value), so when a user clicks the button on your view to add a new extended property, you call that controller method to give you a rendering of the input fields.