How to retrieve users to a dropdownlist from AD with restful service - asp.net-mvc-3

I have MVC3 project whit claim based authentication.
I've managed to get the sign in to work.
What I want to do now is to fill a DropDownList with with groups, then another DropDownlist with users belonging to this group.
As of now, I fill the DropDownlist with users which are from my local database.
This my method for getting the users from a certain office
private static void GetUsers(UsersContext.Format wFormat)
{
new UsersContext(new Uri("http://site/api/users"), wFormat)
.Users
.Where(x => x.Office.Equals("HomeOffice"))
.ToList()
.ForEach(
item =>
{
var user = item.DisplayName;
});
}
This how my controller get filled now:
public ActionResult Create()
{
var model = new TaskViewModel();
var subjectypes = createNKIRep.GetAllSubjectTypesById();
var customer = createNKIRep.GetAllCustomersByID();
var teams = createNKIRep.GetAllTeamsByID();
var users = createNKIRep.GetAllUsersByID();
model.Teams = new SelectList(teams, "Id", "Name");
model.Users = new SelectList(users, "Id", "Name");
model.SubjectTypes = new SelectList(subjectypes, "Id", "Name");
model.Company = new SelectList(customer, "Id", "CompanyName");
}
return View(model);
This my view where I fill the dropdownlist
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<h4>Get users to customer</h4>
<legend></legend>
<p>Subjecttype</p>
<div class="editor-field">
#Html.DropDownListFor(m => m.SubjectTypeName, Model.SubjectTypes, "Subjecttype", new { #class = "selectstyle" })
#Html.ValidationMessageFor(model => model.SubjectTypeName)
</div>
<p>Team</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.TeamName, Model.Teams, "Team", new { #class = "selectstyle"})
#Html.ValidationMessageFor(model => model.TeamName)
</div>
<p>Users</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.UserName, Model.Users, "Users", new { #class = "selectstyle"})
#Html.ValidationMessageFor(model => model.UsersName)
</div>
<p>Customer</p>
<div class="editor-field">
#Html.DropDownListFor(model => model.CompanyName, Model.Company, "Company", new { #class = "selectstyle" })
#Html.ValidationMessageFor(model => model.CompanyName)
</div>
So my problem is, that I don't know how to fill the Dropdownlist with the values from my AD using restful service. Any idea how it can be done?

Related

Unable to get the value of the combo set to the viewmodel

I have implemented the cascading feature of kendo drop down. While trying to save the information, I am not able to get the value of the combo in my viewmodel. If I comment the name attribute, I do get the value however I need the name attribute for the cascading feature to work. I was trying a workaround using jquery to set the model value but getting errors. Could somebody tell me how to fix this issue.
Sales Organisation Combo
<div class="form-group">
#Html.LabelFor(model => model.Company, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.CountryCode)
.Name("SalesOrganisation")
.HtmlAttributes(new { style = "width:100%" })
.DataTextField("CompanyCodeCompany")
.DataValueField("CountryCode")
.Filter("contains")
.MinLength(3)
.DataSource(dataSource => dataSource
.Read(read => read.Action("RequestHeader_SalesOrganisation", "Request").Type(HttpVerbs.Post))
.ServerFiltering(true)
)
)
</div>
#Html.ValidationMessageFor(model => model.Company, "", new { #class = "text-danger" })
</div>
</div>
Sales Office combo
<div class="form-group">
#Html.LabelFor(model => model.SalesOffice, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.SalesOfficeID)
// .Name("SalesOffice")
.HtmlAttributes(new { style = "width:100%" })
.DataTextField("SalesOffice")
.DataValueField("SalesOfficeID")
.AutoBind(false)
.Value("")
.DataSource(dataSource => dataSource
.Read(read =>
{
read.Action("RequestHeader_SalesOffice", "Request")
.Type(HttpVerbs.Post)
.Data("GetFilterOption");
}).ServerFiltering(true)
).CascadeFrom("SalesOrganisation").Filter("contains")
)
</div>
#Html.ValidationMessageFor(model => model.SalesOffice, "", new { #class = "text-danger" })
</div>
</div>
Javascript for cascading feature to work
function GetFilterOption() {
return {
id: $('#SalesOrganisation').val()
}
}
Javascript - Trying to set the model which doesnt work
function GetFilterOption() {
var countryCode = $('#SalesOrganisation').val();
var model = $('#SalesOrganisation').data('kendoComboBox');
model.value = countryCode;
return id = countryCode;
}
When you use .ComboBoxFor(), you should not use .Name().
When you use .ComboBoxFor(m => m.FieldName) then the id/name attribute will be set to "FieldName" by kendo's implementation of the Razor helper and matches the name of your model field.
If you then use .Name("SomeOtherFieldName"), you change the id/name attribute to "SomeOtherFieldName" and it no longer matches the field name of your model, which is why you no longer get the value.
What you want to do is not use .Name() and set up the .CascadeFrom() appropriately, i.e.
#(Html.Kendo().ComboBoxFor(model => model.CountryCode)
....
#(Html.Kendo().ComboBoxFor(model => model.SalesOfficeID)
.CascadeFrom("CountryCode")
function GetFilterOption() {
return {
id: $('#CountryCode').val()
}
}

populating textboxes based on selection of kendo combo box

I need to populate two textbox controls based on a selection of combo box in my MVC 5 application. The combo box is a kendo MVC control. The values that need to be assigned to the text box controls are there in the collection that is bound to the combo box control. Could somebody let me know how to go about it. Does this need to be handled in javascript/ jquery or is it handled in kendo combo box events. An example would be great.
Combo box
#Html.LabelFor(model => model.Name1, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-4">
<div class="editor-field">
#(Html.Kendo().ComboBoxFor(model => model.Name1)
.HtmlAttributes(new { style = "width:300px" })
.DataTextField("Name1")
.DataValueField("CustomerMasterDataId")
.DataSource(dataSource => dataSource
.Read(read => read.Action("RequestHeader_CustomerData", "Request").Type(HttpVerbs.Post))
)
)
</div>
#Html.ValidationMessageFor(model => model.CustomerNumber, "", new { #class = "text-danger" })
</div>
Textbox
<div class="form-group">
#Html.LabelFor(model => model.CustomerNumber, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#Html.EditorFor(model => model.CustomerNumber, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.CustomerNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="clearfix"></div>
<div class="form-group">
#Html.LabelFor(model => model.CustomerGroup, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
<div class="editor-field">
#Html.EditorFor(model => model.CustomerGroup, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.CustomerGroup, "", new { #class = "text-danger" })
</div>
</div>
Controller method that poulates the combo
public ActionResult RequestHeader_CustomerData()
{
var response = requestRepository.GetCustomerData().AsQueryable().ProjectTo<CustomerViewModel>();
var jsonResult = Json(response, JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
Please note that the CustomerNumber and Name1 field would be used to populate the text boxes
ViewModel
public class CustomerViewModel
{
public int CustomerMasterDataId { get; set; }
public int CustomerNumber { get; set; }
[Display(Name = "Customer Name")]
public string Name1 { get; set; }
[Display(Name = "Customer Group")]
public string CustomerGroup { get; set; }
}
Yes, handle the change event:
#(Html.Kendo().ComboBoxFor(model => model.Name1)
.HtmlAttributes(new { style = "width:300px" })
.DataTextField("Name1")
.DataValueField("CustomerMasterDataId")
.DataSource(dataSource => dataSource
.Events(e => e.Change(onComboChange))
.Read(read => read.Action("RequestHeader_CustomerData", "Request").Type(HttpVerbs.Post))
)
)
Now handle it in js:
#section scripts
{
<script type="text/javascript">
function onComboChange(e) {
var dataItem = e.sender.dataItem();
if (dataItem) {
//set the value of text box (input)
$("#CustomerNumber").val(dataItem.CustomerNumber);
$("#CustomerGroup").val(dataItem.CustomerGroup);
};
};
</script>
}
Here is a js equivalent: http://jsfiddle.net/sg53719/74LwhebL/1/

Edits in List not being saved when partial view loaded MVC

I'm new to MVC. I have a view which displays the products attached to a Quote (the QuoteDetails). I also have an Ajax.ActionLink)_ for "Add product" which loads a partial view for another product to be entered. The problem is that when the partial view is loaded, edits to the other products not in the partial view are not saved. If no partial view is loaded, edits to the listed products are saved just fine.
Here is the relevant code for the main view:
#model CMSUsersAndRoles.Models.QuoteViewModel
....
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery.mask.min.js"></script>
#using (Html.BeginForm())
{
....
#Html.HiddenFor(model => model.CustomerId)
#Html.LabelFor(model => model.QuoteId)
#Html.EditorFor(model => model.QuoteId, new { htmlAttributes = new { #readonly = "readonly", #class = "form-control" } })
#Html.ValidationMessageFor(model => model.QuoteId)
.... // more controls for properties of Quote
#Html.LabelFor(model => model.QuoteDetail)
<div id="QuoteDetails">
#for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
#Html.HiddenFor(model => model.QuoteDetail[i].QuoteId, new { htmlAttributes = new { #class = "form-control" } })
....
#Html.EditorFor(model => model.QuoteDetail[i].SKU, new { htmlAttributes = new { #readonly = "readonly", #id = "SKU", #class = "form-control", style = "width: 100px" } })
#Html.EditorFor(model => model.QuoteDetail[i].Amount, new { htmlAttributes = new { #class = "form-control amount", style = "width: 95px" } })
#Html.ValidationMessageFor(model => model.QuoteDetail[i].Amount)
.... // more for controls for properties of QuoteDetail
#Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteDetail[i].QuoteId, quoteDetailId = (Model.QuoteDetail[i].QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.QuoteDetail[i].ProductName,
}, new { #class = "btn btn-danger glyphicon glyphicon-trash" })
</div>
}
#Html.EditorFor(model => model.Subtotal, new { htmlAttributes = new { #class = "form-control subTotal", style = "width: 100px; float:right; clear:left; text-align:right" } })
#Ajax.ActionLink("Add product", "AddProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetail.Count + 1) },
new AjaxOptions
{
UpdateTargetId = "QuoteDetails",
InsertionMode = InsertionMode.InsertAfter
})
}
Here is the partial view:
#model CMSUsersAndRoles.Models.QuoteDetail
#{
ViewBag.Title = "EditQuoteDetail";
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="row" class="row">
<table>
#using (Html.BeginCollectionItem("quoteDetail"))
{
<tr>
#Html.HiddenFor(model => model.QuoteId, new { htmlAttributes = new { #class = "form-control" } })
#Html.EditorFor(model => model.SKU, new { htmlAttributes = new { #readonly = "readonly", #id = "SKU", #class = "form-control", style = "width: 100px" } })
#Html.DropDownListFor(model => model.ProductId, new SelectList(ViewBag.ProductData, "ProductId", "Name"), "---Select one---", new { style = "width: 300px !important", htmlAttributes = new { #id = "ProductName", #class = "ProductList" } });
.... // more controls for properties of QuoteDetail
#Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetailId) },
new AjaxOptions
{
HttpMethod = "POST",
Confirm = "Are you Sure You Want to Delete " + Model.ProductName,
}, new { #class = "btn btn-danger glyphicon glyphicon-trash" })
</tr>
}
</table>
</div>
And here is the controller action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(QuoteViewModel qvm,
[Bind(Include = "CustomerId,SalesRep,FirstName,LastName,Company,Address1,Address2,City,State,PostalCode,WorkPhone,CellPhone,Email,Discount,PaymentTerms")] Customer customer,
[Bind(Include = "QuoteId,QuoteDetailId,ProductId,ProductName,Amount,ListPrice,Discount,Price")] List<QuoteDetail> quoteDetails,
[Bind(Include = "QuoteId,CustomerId,Subtotal,Tax,Total,QuoteDate,GoodUntil,QuoteSent,DateApproved,DateOrdered")] Quote quote)
{
....
}
Can anyone help with this? Any help will be much appreciated.
Your using 2 different techniques here to generate your collection which is causing the issue.
In the main view you have a for loop to generate controls for existing items which is generating the zero-based consecutive indexers, which is what the DefaultModelBinder uses by default. Your html will include name attributes that are for example
<input name="QuoteDetail[0].QuoteId"..../>
<input name="QuoteDetail[1].QuoteId"..../>
<input name="QuoteDetail[2].QuoteId"..../>
But then you add new items using the BeginCollectionItem helper method which generates the collection indexer as a Guid so that new inputs will be (where xxx is a Guid)
<input name="QuoteDetail[xxxx].QuoteId"..../>
and also includes a
<input name="QuoteDetail.Index" value="xxxx" ... />
which is used by the DefaultModelBinder to match non zero-based non consecutive indexers. You cannot use both techniques.
To solve this, you can either add an input for the indexer in the for loop
#for (int i = 0; i < Model.QuoteDetail.Count; i++)
{
....
<input type="hidden" name="QuoteDetail.Index" value="#i" />
}
or change the loop to use the partial view containing the BeginCollectionItem method in each iteration
#foreach(var item in Model.QuoteDetail)
{
#Html.Partial("xxxx", item) // replace xxxx with the name of your partial
}

MVC 5 Ajax form with field updates asynchronously and still supporting a Full form post

So I have been using MVC for a while but not a lot of Ajax.
So the issue i have is that I have a create view where the first field of the create view is a Date picker which on change i want ajax to change the selection dropdown of another field on the form. I have the Ajax update working , but the form Post (Create button), now only calls into the Ajax method on the controller. I want the Ajax post back to call the default method Create method on the Controller. So the Create form contains 3 fields
A date (which has the OnChange Ajax submit)
A drop down list of id's and text
other fields as required
I have included the model and cshtml view files (one the partial). The controller is just simply a method taking either the datetime value or the entire model.
So I have the code working where, when the date changes it updates the relevant LocalIds field, but because the 'create' button is inside the Ajax.BeginForm tags, when the create button is pressed, it generates an Ajax call, and I want it to generate a Form Post. What am i missing
CreateModel
public class IdsSelection
{
public string Id { get; set; }
public List<SelectListItem> Selections { get; set; }
}
public class CreateModel
{
[Display(Name="Local Id's")]
public IdsSelection LocalIds;
[Display(Name="Day")]
[Required, DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",ApplyFormatInEditMode=true)]
public DateTime Date { get; set; }
[Required, Display(Name = "Other Value")]
[Range(1.0, 1000000.0, ErrorMessage ="Value must be greater than zero")]
public decimal OtherValue { get; set; }
public CreateModel()
{
Date = DateTime.Today;
}
}
CreateView.cshtml
#Model Demo.Models.CreateModel
....
#using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "changeid",
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new
{
htmlAttributes = new
{
autofocus = "autofocus",
#class = "form-control",
#Value = Model.Date.ToString("yyyy-MM-dd"),
onchange = "$(this.form).submit();"
}
})
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_ShowIds", Model.LocalIds)
<div class="form-group">
#Html.LabelFor(model => model.OtherValue, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OtherValue, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OtherValue, "", new { #class = "text-danger" })
</div>
</div>
<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 {
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
}
_ShowIds.cshtml
#model Demo.Models.IdsSelection
<div id="changeid" class="form-group">
#Html.Label("Local Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#if(Model.Selections.Count == 1) // one
{
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Selections[0].Text, new
{
htmlAttributes = new
{
#class = "form-control",
#readonly = "readonly",
}
})
}
else // more entries so show a dropdown
{
#Html.DropDownListFor(model => model.Id, Model.Selections, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model, "", new { #class = "text-danger" })
}
</div>
</div>
You have not shown you controller methods, but assuming the method which generates this view is named Create(), then create a corresponding POST method
[httpPost]
public ActionResult Create(CreateModel model)
for saving the data. The remove #using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions() { ..... ])) and replace with a normal form to post back to the server (and you can remove jquery.unobtrusive-ajax.min.js)
#using (Html.BeginForm())
{
....
Next create a controller method that returns your partial view based on the selected date
public PartialViewResult FetchLocalIds(DateTime date)
{
IdsSelection model = // populate model based on selected date
return PartialView("_ShowIds", model);
}
Next, in the view, wrap the current #Html.Partial() in a placeholder element
<div id="localids">
#Html.Partial("_ShowIds", Model.LocalIds)
</div>
Then use jquery to handle the datepickers .change() event and call the FetchLocalIds() method to update the DOM using the .load() function.
$('#Date').change(function() {
$('#localids').load('#Url.Action("FetchLocalIds")', { date: $(this).val() })
})
Note also to remove onchange = "$(this.form).submit();" from the #Html.EditorFor(model => model.Date, new { ... })

Entity framework update shows dbconcurrency while updating a record?

in my code the update takes place both in the view and in the controller. Same Controller and View for both create and Update. Create profile works fine. but while updating it shows DbConcurrency exception Message. Please help me to find.
Exception Message while updating the record:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
My Update profile page has (Profile.cshtml)
#model Sitecss.Models.Profile
#using Microsoft.Web.Helpers;
#{
ViewBag.Title = "CreateProfile";
Layout = "~/Views/Shared/_HomeLay.cshtml";
}
#{
var GT = new SelectList(new[] {
new {ID ="Team DeathMatch", Name="Team DeathMatch"},
new {ID ="Search & Destroy", Name="Search & Destroy"},
new {ID ="Flag Runner", Name="Flag Runner"},
new {ID ="Domination", Name="Domination"},
new {ID ="Kill Confirmed", Name="Kill Confirmed"}
},"ID","Name");
var Spec = new SelectList(new []{
new {ID ="Assault", Name="Assault"},
new {ID ="Tactical", Name="Tactical"},
new {ID ="Long-Range Eliminations", Name="Long-Range Eliminations"},
new {ID ="Noob", Name="Noob"}
}, "ID", "Name");
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm("CreateProfile", "Home", FormMethod.Post, new { #encType = "multipart/form-data" }))
{
<div id="content1">
#Html.ValidationSummary(true)
<h4>Create a Profile</h4>
<div>
#Html.LabelFor(m => m.SteamName)
</div>
<div>
#Html.TextBoxFor(m => m.SteamName, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.SteamName)
</div>
<div>
#Html.LabelFor(m =>m.UserImg)
</div>
<div>
<input type="file" name="image" class="image" /> <br />
</div>
<div>
#Html.LabelFor(m => m.GameType)
</div>
<div>
#Html.DropDownListFor(m => m.GameType, GT, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.GameType)
</div>
<div>
#Html.LabelFor(m => m.Specialist)
</div>
<div>
#Html.DropDownListFor(m => m.Specialist, Spec, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.Specialist)
</div>
<div>
#Html.LabelFor(m => m.FavGun)
</div>
<div>
#Html.TextBoxFor(m => m.FavGun, new { #class = "wide" })
#Html.ValidationMessageFor(m => m.FavGun)
</div>
<p><input type="submit" class="button" value="Ok" /></p>
</div>
}
while my controller functions are
public ActionResult CreateProfile()
{
if (db.Profiles.Any(u => u.Username == User.Identity.Name))
{
Profile pro = (from usr in db.Profiles where usr.Username == User.Identity.Name select usr).Single();
olf = pro.UserImg;
Profile p = db.Profiles.Find(pro.Id);
ViewBag.ProfilePic = olf;
return View(p);
}
else
{
ViewBag.Name = User.Identity.Name;
return View();
}
}
[HttpPost]
public ActionResult CreateProfile(Profile m)
{
WebImage photo = WebImage.GetImageFromRequest();
string newFileName = "";
string thumbs = "";
if (photo != null)
{
string ext = Path.GetExtension(photo.FileName);
newFileName = User.Identity.Name+ ext;
thumbs = #"Images/" + newFileName;
photo.Resize(width: 120, height: 120, preserveAspectRatio: true, preventEnlarge: true);
photo.Save(#"~/"+thumbs);
m.UserImg = newFileName;
}
if (ModelState.IsValid)
{
if (db.Profiles.Any(u => u.Username == User.Identity.Name))
{
db.Entry(m).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
m.Username = User.Identity.Name;
db.Profiles.Add(m);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(m);
}
While Adding Breakpoint to the update statement in my edit Controller I came to know that the primary key Id =0 on update in order to fix this issue I have added Hidden Field in the view that has fixed the DbConcurrency on update

Resources