Before I start I'll just say that I've looked at other answers before posting and none specifically help me.
I need to create a Kendo UI grid in ASP.NET MVC that changes depending on what the users selects from a DropDownList. I will eventually be using data from a database, but currently I'm trying to learn with random hard-coded data.
I found a tutorial online that shows me how to do it with data from a sample database, but I can't set that up for reasons I cant explain. So I'm trying to adapt the code from that tutorial to work with my controllers and models. This might be set up completely wrong as I'm relatively new to ASP.NET MVC.
So here's the tutorial I'm trying to follow.
This is my controller:
public class LookupValueController : Controller
{
private List<LookupModel> tables = new
List<LookupModel>()
{ new LookupModel() { TableName = "Table1",
Description = "Table 1" },
new LookupModel() { TableName = "Table2",
Description = "Table 2" } };
private List<LookupValueModel> values = new List<LookupValueModel>()
{ new LookupValueModel() { TableName = "Table1", Description = "Value 1", LookupCode = "1" },
new LookupValueModel() { TableName = "Table2", Description = "Value 2", LookupCode = "2"} };
// GET: LookupValue
public ActionResult Index()
{
return View();
}
public ActionResult GetAllTableA()
{
try
{
var table = tables;
return Json(table, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(ex.Message);
}
}
public ActionResult GetAllTableB()
{
try
{
var value = values;
return Json(value, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(ex.Message);
}
}
}
Then my 2 models:
public class LookupValueModel
{
public string TableName { get; set; }
public string LookupCode { get; set; }
public string Description { get; set; }
}
public class LookupModel
{
public string TableName { get; set; }
public string Description { get; set; }
}
I've tried just changing the values in the view in the tutorial but it doesn't work, as I believe it isn't as simple as just changing some text.
I'm pretty stuck for how to do this and don't know where to go from here. I know this is a very long winded post with lots of code, but I would really appreciate some help.
Where am I going wrong adapting the tutorial code? What do I have to change to get it to work with hard-coded data?
That's not that hard. What you need to do is to change the DataSource's url for each Action you want. So, depending on what options user selects in the DDL, you change the DataSource. Check this demo.
What you need to change in from the above demo is that your grid's DataSource will call an url instead of a hard-coded json, right? In that url, you change the desired action:
let changeTableData = function changeTableData(option) {
let dataSource = new kendo.data.DataSource({
transport: {
url: "MyApp/" + option
}
});
$("#grid").data("kendoGrid").setDataSource(dataSource);
};
It will read the new url and fetch the data into the grid and updated it.
UPDATE
The transport url ir the url path to your action, e.g.
let url;
if (option == "A") {
url = "#Url.Action("TableA")";
}
else if (option == "B") {
url = "#Url.Action("TableB")";
}
let dataSource = new kendo.data.DataSource({
transport: {
url: url
}
});
1) Remove the grid from this view and create a new partialview and just have the grid located in that.
Now this can be one of two ways. Either an onclick via the drop down list or an onchange. Your choice
function Getdropdown()
{
var id = $("#//dropdownID").val(); //Get the dropdown value
var json = '{dropdownId: ' + id + '}';
$.ajax({
url:'#Url.Action("ViewGrid", "//Controller")',
type:'POST',
data:json,
contentType:'Application/json',
success:function(result){
$("//The Id of of the div you want the partial to be displayed in in the cshtml").html(result);
}
});
}
2) Get the value of the dropdown and pass it to a controller method that calls this new partial view, sending it the ID in a model
public ActionResult ViewGrid(int dropdownId)
{
AModel model = new AModel
{
DropDownID = dropdownId
};
return PartialView("_theGridPartial", model);
}
3) Change your grid to look like this:
#(Html.Kendo().Grid<KendoMvcApp.Models.EmployeeA>()
.Name("EmpGrid")
.Selectable()
.Columns(columns =>
{
columns.Bound(c => c.FirstName);
columns.Bound(c => c.LastName);
})
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetAllEmployee", "GridDataSource", new {id = Model.DropDownID}))
)
)
4) This is the new Controller read
public ActionResult GetAllEmployee([DataSourceRequest]DataSourceRequest request, int id)
{
try
{
//Have a call that gets the table data based on the id you are passing into here. This id will be the table id you have got from your dropdown list
}
catch (Exception ex)
{
return Json(ex.Message);
}
}
This should allow you to change the table based on the dropdown.
Related
I am showing search results same as searching groups on facebook
enter image description here
I have a relationship Table named CommunityUser in Database having attributes CommunityID and UserID.
Using Partial View I want to show if User not already joined that Community/Group that it will show Join Button else if user already joined that community it will show Leave button.
I have written IsMember() function in my controller that takes two parameters, CommunityID and UserID. This will return true if that Community ID exist against that user ID.
public bool IsMember(string UserID, int CommunityID) {
var Membership = db.Users.Include(x => x.CommunityUsers).Where(s => s.Id.Equals(UserID)).Count();
if(Membership>0)
return true;
else
return false;
}
Now what I actually need is, I want to call this function in an IF condition on my view class. It is not allowing me to call this function on my view Class.
#if (){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
In your controller you should have a method which will return this view. So in this method you call this function
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
return View(hasMembership);
}
In the View it self then you just grab this variable hasMembership you just passed from #model.
#if (Model){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
Note: it might be wise to create some DTO class for passing data to a view, because you might need to pass multiple value to a view at some point. Plus the whole condition would be more readable
public SomeDTO {
public bool IsMember {get;set}
public List<Community> Communities {get;set;}
}
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
var listOfCommunities = _repo.GetComunities();
var dto = new SomeDTO
{
IsMember = hasMembership,
Communities = listOfCommunities
}
return View(dto);
}
#if (Model.IsMember){
// do or do not something
}
This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 6 years ago.
In my MVC project I pass list of currencies to the view within the drop down list. However, once I try to post the view I get the following exception:
The ViewData item that has the key 'FromCurrencyId' is of type
'System.Int32' but must be of type 'IEnumerable'.
Currency Controller
namespace Project.Controllers
{
public class CurrencyController : Controller
{
[HttpGet]
// GET: Currency
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll().ToList();
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
return View(model);
}
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (ModelState.IsValid)
{
if (cur.FromCurrencyId == cur.ToCurrencyId)
{
//do something if same currecnies and return.
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else
{
some code .....
}
}
return View(cur);
}
}
}
Currencies VM
namespace Project.ViewModels
{
public class Currencies
{
public int Id { get; set; }
[Required]
public int FromCurrencyId { get; set; }
public SelectList FromCurrencies { get; set; }
[Required]
public int ToCurrencyId { get; set; }
public SelectList ToCurrencies { get; set; }
public string CurrencyName { get; set; }
public string CurrencyCountry { get; set; }
[Required]
public decimal ConversionRate { get; set; }
public decimal Value { get; set; }
public SelectList AvailableCurrencies { get; set; }
}
}
CurrencyClient web service VM
namespace Project.ViewModels
{
public class CurrenciesClient
{
private string base_Url = "http://localhost:51646/api/";
public IEnumerable<Currencies> findAll()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(base_Url);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("currencies").Result;
if (response.IsSuccessStatusCode)
{
var resposeData = response.Content.ReadAsStringAsync().Result;
var Currency = JsonConvert.DeserializeObject<List<Currencies>>(resposeData);
return Currency;
}
return null;
}
catch
{
return null;
}
}
}
}
Index View
model Project.ViewModels.Currencies
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Currency", FormMethod.Post))
{
#Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
#Html.DropDownListFor(m => m.FromCurrencyId, Model.FromCurrencies as IEnumerable<SelectListItem>)
#Html.DropDownListFor(m => m.ToCurrencyId, Model.ToCurrencies as IEnumerable<SelectListItem>)
<button type="submit" class="btn btn-primary">Convert</button>
}
This problem is becuase you are passing null value from your dropdown.Means you are not selecting any value. Check that if you will pass some value from dropdown it will work fine.To solve this problem you need to add the same
code
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
in your controller index post method.Because if selectListitem would be null the following code will be executed
IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>;
if (selectList == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
MvcResources.HtmlHelper_WrongSelectDataType,
name, o.GetType().FullName, "IEnumerable<SelectListItem>"));
}
Which will throw exception.
(It would be better if you will use
ViewBag.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
like this.)
The better description is given here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
The whole explanation is also given in this link like how does this code work.
you will have to set the Dropdown data in the post controller as well, otherwise it will not be able to find the ViewBag values, as a result when after post action it calls the Index view, the ViewBag.FromCurrencies and ViewBag.ToCurrencies will be null which is obviously that we don't want.
For fixing the error, you will have to change you post action to be like:
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (ModelState.IsValid)
{
if (cur.FromCurrencyId == cur.ToCurrencyId)
{
//do something if same currecnies and return.
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else
{
some code .....
}
}
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll().ToList();
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
return View(cur);
}
You should not return the view from your POST action or you will run into many issues. Here is the problem with that:
When you submit the form the URL is pointing to your Index. The body of your http post will have a bunch of Currencies items in it. Therefore, MVC, will submit the form to your Index method with Currencies cur parameter.
If all is well you return the same view.
If you refresh the page, your browser will simply reissue the last request and guess what, it will submit the form again. But this is not what you intended by refreshing. You wanted to get the form as it was originally presented not resubmit it.
Therefore instead of returning a view from a POST, you should always, except if AJAX was used, return a redirect.
In this case if all goes well, you may want to send the user to a success page or some other page so you should do this:
return RedirectToAction("YourActionName", "YourControllerName");
This pattern is called the PRG pattern. What this does is this:
user submits a form
If all goes well on the server side, you tell the browser to issue another request and get another page.
The browser gets the other page which may be a success page.
Now the user is on the success page. If they hit refresh they will get the success page again. They will not be submitting the same form over and over.
I'm currently trying to implement a Dropdown List with what I would assume is hardcoded values. Basically what I want is to have a Dropdown List with a choice of three possible values.
I have a total of 4 controllers and views that will be using this dropdown. I've seen a lot of examples for MVC2 and MVC3 where people have hard coded their dropdowns in their views, and I personally don't prefer to go with a quick and "dirty" fix such as that.
I have a model containing the following.
public class Status
{
public int id { get; set; }
public string status { get; set; }
public Status(int statusId, string statusName)
{
id = statusId;
status = statusName;
}
}
The status should be able to have any of the 3 possible values:
Active
Inactive
Processing
I thought of creating the status' using this method I currently have in my status class:
public static List<Status> getAllStatus()
{
List<Status> states = new List<Status>();
states.Add(new Status(1, "Active"));
states.Add(new Status(2, "Inactive"));
states.Add(new Status(3, "Processing"));
return states;
}
I haven't been able to figure out how to use this model inside my Controllers alongside with how to pass it along to my views and was hoping someone in here would known how to do that?
EDIT1:
I guess I forgot to mention that I will be storing the selected value as a string in my database and that I am using a view which doesn't have the model of my status class, but rather the model of object which I will be storing in my database (which might be the case of a vehicle object).
EDIT2:
I have a model called Customer, which has some of the following values:
public int CustomerID { get; set }
public string Email { get; set }
public string Phone { get; set }
public Status Status { get; set; }
In my DB for my Customer model I have a string in which I wan to store the selected Status.
So basically I wan't to change the following to a dropdown with 3 options, Inactive, Active and Processing.
However I don't want to code this in my view as I will be needing it in 8 different views and copy pasting that is not very sleek code.
#Html.DropDownListFor(m => m.status_id, new SelectList(getAllStatus(), "id", "status"))
It doesn't make much sense to save it as a string within your database as it sounds more like something static. So u should consider an Enum. To me more precise look to my previous answer and add those Model properties to a ViewModel.
public class CustomerViewModel () {
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
}
Pass this into your View through your controller:
public class CustomerCOntroller(){
public ActionResult Index(){
CustomerViewModel viewModel = new CustomerViewModel();
return View(viewModel);
}
}
And you are done. If u are more working with a list which u need to build up add it to your viewModel object.
Greetings,
S..
To start you have a lot of vague questions. Be more specific if you can. If you don't know how MVC works that well I would recomment to follow some tutorials on it.
Model.cs (A ViewModel is preferred). You Should create a ViewModel which you passes to the View. Below is an example how to get a list of items.
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
StatusTypeEnum.cs
public enum StatusTypeEnum()
{
[Description("Active")] // For correct naming
Active,
Inactive,
Processing
}
View.cshtml
#Html.DropDownListFor(x => Model.SelectedStatusId, Model.StatusItems)
EnumAttribute.cs (To read the Annotation Descriptions. And don't try to understand this. It's just magic. It gets the DataAnnotation of the enum types by reflection.)
public static class EnumAttribute
{
public static string GetDescription<TEnum>(this TEnum value)
{
var fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
}
You could declare States as public propery in your class and use this to access it in your views:
<ComboBox Grid.Column="1" Grid.Row="0" Margin="5"
VerticalAlignment="Center" ItemsSource="{Binding States}"
IsTabStop="False"}"/>
I am new to MVC (I am moving over from the dark side of traditional ASP.Net) and I know that SO is more of a "why doesn't this work" but, being new to MVC, I just wanted to ask how something is achieved - I don't really have any code or markup because I don't know how at the moment.
Right, using an analogous example... I have a form that has a drop-down of a list of "Widgets" (have that working, thanks to SO) ... and then there are other fields (Length/Height/Width) which have "default" values.
When the form displays, the Drop-Down is shown but the form fields of L/H/W are empty/disabled until the user selects one from the DDL.
Now, in clasic ASP.Net world, you would do a PostBack on the "onselectedindexchange" and that would look at the item selected, then update the L/H/W fields with values from the "master widget entry" version.
As MVC does not have post back... how is this achieved?
In Asp.Net MVC, There is no postback behaviour like you had in the web forms when a control value is changed. You can still post the form and in the action method, you may read the selected value(posted value(s)) and load the values for your text boxes and render the page again. This is complete form posting. But there are better ways to do this using ajax so user won't experience the complete page reload.
What you do is, When user changes the dropdown, get the selected item value and make a call to your server to get the data you want to show in the input fields and set those.
Create a viewmodel for your page.
public class CreateViewModel
{
public int Width { set; get; }
public int Height{ set; get; }
public List<SelectListItem> Widgets{ set; get; }
public int? SelectedWidget { set; get; }
}
Now in the GET action, We will create an object of this, Initialize the Widgets property and send to the view
public ActionResult Create()
{
var vm=new CreateViewModel();
//Hard coded for demo. You may replace with data form db.
vm.Widgets = new List<SelectListItem>
{
new SelectListItem {Value = "1", Text = "Weather"},
new SelectListItem {Value = "2", Text = "Messages"}
};
return View(vm);
}
And your create view which is strongly typed to CreateViewModel
#model ReplaceWithYourNamespaceHere.CreateViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(s => s.SelectedWidget, Model.Widgets, "Select");
<div id = "editablePane" >
#Html.TextBoxFor(s =>s. Width,new { #class ="myEditable", disabled="disabled"})
#Html.TextBoxFor(s =>s. Height,new { #class ="myEditable", disabled="disabled"})
</div>
}
The above code will render html markup for the SELECT element and 2 input text fields for Width and Height. ( Do a "view source" on the page and see)
Now we will have some jQuery code which listens to the change event of the SELECT element and reads the selected item value, Makes an ajax call to server to get the Height and Width for the selected widget.
<script type="text/javascript">
$(function(){
$("#SelectedWidget").change(function() {
var t = $(this).val();
if (t !== "") {
$.post("#Url.Action("GetDefault", "Home")?val=" + t, function(res) {
if (res.Success === "true") {
//enable the text boxes and set the value
$("#Width").prop('disabled', false).val(res.Data.Width);
$("#Height").prop('disabled', false).val(res.Data.Height);
} else {
alert("Error getting data!");
}
});
} else {
//Let's clear the values and disable :)
$("input.editableItems").val('').prop('disabled', true);
}
});
});
</script>
We need to make sure that we have an action method called GetDetault inside the HomeController to handle the ajax call.
[HttpPost]
public ActionResult GetDefault(int? val)
{
if (val != null)
{
//Values are hard coded for demo. you may replae with values
// coming from your db/service based on the passed in value ( val.Value)
return Json(new { Success="true",Data = new { Width = 234, Height = 345}});
}
return Json(new { Success = "false" });
}
Make a Controller "Action" that return "Json" data.
Make Ajax call "onchange" of dropdown to that "Action".
On ajax "response" (json) u will get values then set those values to
fields from json response.
This is the way to update field values.
Shyju made a brilliant post in 2015 but I had to update it to make it work for MVC 5. I worked with one of my progammers (I'm an IT manager) to create this. You need to create a class to represent the dropdown and the Height and Width.
public class AjaxText
{
public int Width { set; get; }
public int Height { set; get; }
public List<SelectListItem> Widgets { set; get; }
public int? SelectedWidget { set; get; }
}
In my HomeController.cs, the GET action will create an object of this, initialize the Widgets property and send to the view.
public IActionResult AjaxText()
{
//Hard coded for demo. You may replace with data form db.
AjaxText vm = new AjaxText();
vm.Widgets = new List<SelectListItem>
{
new SelectListItem {Value = "1", Text = "Weather"},
new SelectListItem {Value = "2", Text = "Messages"}
};
return View(vm);
}
And your create view will render html markup for the SELECT element and 2 input text fields for Width and Height. ( Do a "view source" on the page and see)
#model AjaxText
#{
ViewData["Title"] = "AjaxText";
}
<h1>#ViewData["Title"]</h1>
#using(Html.BeginForm())
{
#Html.DropDownListFor(s => s.SelectedWidget, Model.Widgets, "Select");
<div id = "editablePane" >
#Html.TextBoxFor(s =>s. Width,new { #class ="myEditable", disabled="disabled"})
#Html.TextBoxFor(s =>s. Height,new { #class ="myEditable", disabled="disabled"})
</div>
Now we will have some code which listens to the change event of the SELECT element and reads the selected item value, makes an ajax call to server to get the Height and Width for the selected widget. I added some alerts to help you debug.
<script type="text/javascript">
$(function(){
$("#SelectedWidget").change(function() {
var t = $(this).val();
if (t !== "")
{
$.ajax({
type: 'POST',
datatype: 'json',
url: '/Home/GetDefault?val=' + t,
success: function (bbb) {
alert(t);
alert(bbb.success);
alert(bbb.info.height);
$("#Width").prop('disabled', false).val(res.Data.Width);
$("#Height").prop('disabled', false).val(res.Data.Height);
},
error: function (msg) {
alert("error");
}
});
} else {
//Let's clear the values and disable :)
$("input.editableItems").val('').prop('disabled', true);
}
});
});
</script>
And in my home controller, the Post is done almost the same as how Shyju did it, but success doesn't have quotes around true and false. And you don't have to use the word data... info or whatever will work too. But keep it lowercase to maintain your sanity.
[HttpPost]
public JsonResult GetDefault(int? val)
{
if (val != null)
{
//Values are hard coded for demo. you may replae with values
// coming from your db/service based on the passed in value ( val.Value)
return Json(new { success = true, info = new { width = 234, height = 345 } });
}
return Json(new { Success = false });
}
I'm sure there are better ways to do this. This is what worked for us. Cheers and enjoy your coding experience! :)
I have a web page that is using a number of different partial views and different viewmodels for each partial. One of the partials is for the ability for a user to change their username. Since we are going to allow email addresses as usernames now, I would like to pre-populate the textbox with their current email address from another partial view on the page. How can this be done properly so the value will be populated in the text box and then saved when the submit to the controller happens? Here is a brief code snippet from what I'm looking at:
The view:
#Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change" }) #Html.ValidationMessageFor(model => model.NewUsername)
It's worth noting here that I have tried setting the current email address into ViewData and ViewBag and putting "#value = viewdatahere" into the textbox for properties, but this didn't populate the string, it just left it blank.
I just need to know how this is done. Any help is appreciated.
Edit to add controller POST and GET methods:
[HttpGet]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(Guid uniqueUserId)
{
User user = UserManager.GetUser(uniqueUserId);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
ChangeUsername model = new ChangeUsername(){UserGuid = user.Identifier,NewUsername = user.Username};
return View(model);
}
[HttpPost]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(ChangeUsername changeUsername)
{
User usr = UserManager.GetUser(changeUsername.UserGuid);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, usr);
if (!ModelState.IsValid)
{
return View(changeUsername);
}
//setup request
SupportUser su = (SupportUser)ViewData["SupportUser"];
RequestData rqd = new RequestData(GetApplicationIdentifer(usr), su.clientIP, su.lanID);
UserUsernameChangeRequest request = new AdminUsernameChangeRequest(rqd,usr,changeUsername.NewUsername);
UserUsernameChangeResponse response = UserManager.ChangeUserUsername(request);
if (response.Status == UserProcessorStatus.Success)
{
var message = ("User has been updated successfully");
TempData["message"] = message;
return PartialView("_NewUsername", changeUsername);
}
switch (response.Status)
{
case UserProcessorStatus.DuplicateUsername:
{
ModelState.AddModelError("NewUsername", "Duplicate username");
changeUsername.AlternateUsernames = response.AlternateUsernames;
return PartialView(changeUsername);
}
default:
{
ModelState.AddModelError("NewUsername", String.Format("An unexpected error occured. Error Code:{0}, Message:{1}", response.Status, response.Message));
return PartialView(changeUsername);
}
}
}
There it is.
The last time that I tried to do this was with MVC 3, but I do know that this technique worked then. It's a stupid difference, that's why I pointed that out first.
You were very close with your attempt at it, but you need to set the property as #Value, not #value. I never looked to hard into why the capital made a huge difference. (Like I said, it's a stupid difference.)
var val = "Dummy Value";
#Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change", #Value = val })
Here's how I'd do it.... in the main page set up a viewmodel that contains the other view models like this:
public class VMMain(){
public void VMMain(){
//don't forget null CTOR as MVC requires it...
}
public void VMMain(Guid userguid, string newusername){
UserGuid = userguid;
NewUserName = newusername;
Part1 = new VM1(UserGuid, NewUserName);
Part2 = new VM2();
Part3 = new VM3();
}
public VM1 Part1 {get;set;}
public VM2 Part2 {get;set;}
public VM3 Part3 {get;set;}
Guid UserGuid {get;set;}
string NewUsername {get;set;}
}
In your main view you can bind to anyone of these viewmodels and properties within them. Just make sure you have a property available to bind.
This would change your controller to look like this:
[HttpGet]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(Guid uniqueUserId)
{
User user = UserManager.GetUser(uniqueUserId);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
var model = new VMMain(){UserGuid = user.Identifier,NewUsername = user.Username};
And now you can bind to say Partial ViewModel 1 that has that property like this:
#Html.TextBoxFor(p => model.Part1.NewUsername,
new { id = "uName_change" })
#Html.ValidationMessageFor(p => model.Part1.NewUsername)
return View(model);
}