Pass one extra parameter along with HttpPostedFileBase for Single File Upload - javascript

In my MVC application I have a View containing
1. One drop down list
2. One File Upload
3. One button for submitting the form.
form code (View)
<form id="upload" enctype="multipart/form-data" action="#Url.Action("ExcelUpload", "NBL")" method="POST">
#Html.DropDownList("CustomerName", new List<SelectListItem>
{
new SelectListItem() {Text = "Customer 1", Value="CM1"},
new SelectListItem() {Text = "Customer 2", Value="CM2"}
}, new { #class = "form-control", #style = "width:auto" })
<input type="file" name="fileUpload" id="fileUpload" size="23" style="margin-top:5px"/>
<button class="btn btn-primary">Upload</button>
</form>
I am able to pass my File in Controller successfully when I click the button.
Controller code
public ActionResult ExcelUpload(HttpPostedFileBase FileUpload)
{
if (FileUpload != null)
{
// Do Stuff here.
}
}
My Problem is I also want the drop down selected value in the controller when I click the button. How can I pass both the Drop down Selected value and the file together in the controller?

The name of the dropdown element is CustomerName and it's within the form. The browser will post it to the server as a key-value pair with the key being the name of the dropdown and the value will be the value the user has selected.
The MVC framework's default binder will look for an action named ExcelUpload that either has a parameter string customerName or the action has a complex type (Model) that has CustomerName as the property.
Change your action to:
ExcelUpload(HttpPostedFileBase FileUpload, string customerName)

The problem is your model as it is does not represent the view or data you want to use. So make a model like so:
using System.ComponentModel.DataAnnotations;
namespace Models
{
public class MyUploadModel
{
[Required]
public HttpPostedFileBase File { get; set; }
[Required]
public string CustomerName { get; set; }
}
}
Use that model in your views to generate the form and then in controller:
public ActionResult ExcelUpload(Models.MyUploadModel myModel)
{
if (ModelState.IsValid)
{
// all good, save
}
return View(myModel);
}
Of course you could just add a string-parameter to your action, but this is much more robust and represents the MVC-pattern (Model/View/Controller).

Related

Loading data into Bootstrap Dual Listbox in ASP.NET Core MVC

I'm working on an ASP.NET Core 2.2 MVC app and am trying to implement Bootstrap Dual Listbox plugin for role selection. I have _UserEditorPartial.cshtml view that can be used to assign roles to a user (the listbox on the right would contain roles assigned):
(The partial has more editable fields, but I think those are irrelevant)
Now, the partial contains data associated with the user I had selected on the parent page. When I select the user, I just pass UserID to ViewUserEditorPartial and query the database to retrieve the whole list of roles available, marking the IsAssigned property to true if the user belongs to the role. So now, I have a list of roles and I know which role belongs to the user.
What I'm struggling with is figuring out how to make sure that the roles belonging to the user end up in in the listbox on the right. If the user belongs to Role2 and Role4, I want my view to be generated like this:
I've found this solution but it's not obvious to me how the two listboxes are correctly populated. I'm thinking after loading the partial I could probably do something with JavaScript, where I separately retrieve the List<RoleUserAssignment> with AJAX and, depending on the value of IsAssigned property for each role, generate the <option> tag in the correct listbox. But I'm wondering is there a better approach?
Also, I'll implement the ability to create users and assign them roles using this solution that I found.
Models:
public class Role
{
public int RoleID { get; set; }
public string RoleName { get; set; }
}
public class User
{
public int UserID { get; set; }
public string UserName { get; set; }
}
public class RoleUserAssignment
{
public RoleUserAssignment()
{
Role = new Role();
User = new User();
}
public Role Role { get; set; }
public User User { get; set; }
public bool IsAssigned { get; set; } //true if user has role
}
public class UserEditing
{
public UserEditing()
{
RoleUserAssignments = new List<RoleUserAssignment>();
}
public List<RoleUserAssignment> RoleUserAssignments { get; set; }
}
HTML
#model UserEditing
<script>
$(document).ready(function () {
$('#rolesSelection').bootstrapDualListbox({});
});
</script>
<form id="userEditorForm">
<div>Roles</div>
<select id="rolesSelection" class="form-control" class="form-control" asp-for="#Model.RoleUserAssignments" asp-items="#(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
multiple="multiple">
</select>
</form>
ViewUserEditorPartial action:
[HttpGet]
public IActionResult ViewUserEditorPartial(int UserID)
{
UserEditing userEditing = new UserEditing();
userEditing.RoleUserAssignments = _userAdmin.GetRoleUserAssignmentsByUserID(_appSettings.MOPConfigConnectionString, UserID);
return PartialView("_UserEditorPartial", userEditing);
}
What I'm struggling with is figuring out how to make sure that the
roles belonging to the user end up in in the listbox on the right.
To achieve this function, you can avoid implementing it in js, it will be easier to implement it in the controller.
You can first get the RoleID data lists that the user belongs to the role, then put the lists into the ViewData in the ViewUserEditorPartial action, and then bind the value of ViewData to the asp-for attribute when binding the select.
Here is my demo:
[HttpGet]
public IActionResult ViewUserEditorPartial(int UserID)
{
UserEditing userEditing = new UserEditing();
var roleUserAssignData = _userAdmin.GetRoleUserAssignmentsByUserID(_appSettings.MOPConfigConnectionString, UserID);
userEditing.RoleUserAssignments = roleUserAssignData;
// get the data which IsAssigned field are true and select the RoleID of each data.
ViewData["SelectedRoles"] = roleUserAssignData.Where(x => x.IsAssigned).Select(x => x.Role.RoleID).ToList();
return PartialView("_UserEditorPartial", userEditing);
}
_UserEditorPartial view:
#model UserEditing
<script>
$(document).ready(function () {
$('#rolesSelection').bootstrapDualListbox({});
});
</script>
<form id="userEditorForm">
<div>Roles</div>
<select id="rolesSelection" class="form-control" class="form-control"
asp-for="#ViewData["SelectedRoles"]"
asp-items="#(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
multiple="multiple">
</select>
</form>
Update
If allowed, add List<int> type field named SelectedRoles in UserEditing model to store the selected roles is better.
public class UserEditing
{
public UserEditing()
{
RoleUserAssignments = new List<RoleUserAssignment>();
}
public List<int> SelectedRoles { get; set; }
public List<RoleUserAssignment> RoleUserAssignments { get; set; }
}
In ViewUserEditorPartial action, change ViewData sentence to the following:
userEditing.SelectedRoles = roleUserAssignData.Where(x => x.IsAssigned).Select(x => x.Role.RoleID).ToList();
_UserEditorPartial view:
<form id="userEditorForm">
<div>Roles</div>
<select id="rolesSelection" class="form-control" asp-for="#Model.SelectedRoles"
asp-items="#(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
multiple="multiple">
</select>
</form>

RadioButtonFor in mvc shows required validation even though not applied required validation

I have one view in which I put two radio button for attribute in my model
I just put data annotation for other field but not the radiobutonfor field but steel it show required validation.Below is my code.I the attribute is int type in model.I used javascript unobtrusive library inn view as well.
<td>
<label>#Html.RadioButtonFor(m => m.OneToOne, 1) Hours </label>
<label>#Html.RadioButtonFor(m => m.OneToOne, 2) Unit </label>
</td>
I am using Html.begin from to post this value.
The RadioButtonFor helper method generates html markup for the radio button input with data-val-required attribute unless you specify the property as nullable type! The jQuery validate plugin does validation on this input because of the existence of this attribute.
If you do not want client side validation on this input, You should change the property type from int to nullable int(int?).
public class YourViewModel
{
// Other properties
public int? OneToOne { set; get; }
}
If radio buttons are not required to select, I personally like to use mutually exclusive checkboxes.
Mainly, if a user accidental selects a radio button, s/he won't be able to uncheck it back unless the user refreshes the entire page. I feel like it is really annoying.
Sample at jsfiddle.net
Model
public class ViewModel
{
public bool OneToOneHours { get; set; }
public bool OneToOneUnit { get; set; }
}
View
#using (Html.BeginForm("Index", "Home", null, FormMethod.Post))
{
<div class="form-control">
#Html.CheckBoxFor(model => model.OneToOneHours, new {#class = "mutually-exclusive"}) Hours
#Html.CheckBoxFor(model => model.OneToOneUnit, new {#class = "mutually-exclusive"}) Unit
</div>
<button id="btnSubmit" type="submit">Submit</button>
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$('input.mutually-exclusive').click(function () {
var checkedState = $(this).val();;
$('input.mutually-exclusive').attr("checked", false);
$(this).prop("checked", checkedState);
});
</script>
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(ViewModel model)
{
int? oneToOne;
if (model.OneToOneHours)
oneToOne = 1;
else if (model.OneToOneUnit)
oneToOne = 2;
return View(model);
}
}

Update label depending on selected value on dropdownlist with knockout

In ASP.NET MVC, I have a form. In this form the user selects a country, and then the ID is posted back to the server, using a normal #using(Html.BeginForm) .
However, for some UX reasons, I use Knockout. Therefore I need to get my observable value countryId to have the value of a dropdownlist.
I want my label in the markup, to show the countryId, depending on the selected value on the dropdownlist.
Markup:
#Html.DropDownListFor(model => model.SelectedCountry, Model.Countries, new Dictionary<string, object> { { "class", "form-control sendaletter_countrylist" }, { "data-bind", "value:countryId" }})
<label data-bind="text: countryId"></label>
ViewModel:
public class CreateSingleLetterModel
{
public CreateSingleLetterModel()
{
this.Countries = new List<SelectListItem>();
}
public string SelectedCountry { get; set; } // expected to be the ID of the SelectListItem
public List<SelectListItem> Countries { get; set; }
}
Then my question is:
How do I modify my DropDownListFor, so the countryId is being set automatically? :-)
Thanks a lot! I really enjoy learning Knockout, but this one has taken me a long time!
All you've done looks correct.
Now you need to define the client-side view model (where countryId will be ko.observable) and call ko.applyBindings
var viewModel = {
countryId: ko.observable(0)
};
ko.applyBindings(viewModel);
example: http://jsfiddle.net/tabalinas/xJ7mm/

How to pass js variable to #Model.MyModel (MVC4)

Here are my models
public class AddressBook
{
public string UserId { get; set; }
public IList<Address> Addresses { get; set; }
public AddressBook()
{
UserId = "";
Addresses = new List<Address>();
}
}
public class Address
{
public string Company { get; set; }
public string Title { get; set; }
public string FName { get; set; }
...
}
The controller builds the AddressBook with a list of addresses.
The main page uses the AddressBook model (#model mymodel.AddressBook) and I can access the different addresses using Model.Addresses[index].
On the page I display the list of addresses each with an Edit button (I stripped the html code off for clarity):
#model mymodel.AddressBook
...
#for (int i = 0; i < Model.Addresses.Count; i++)
{
#Model.Addresses[i].Company
#Model.Addresses[i].FName
...
#:<input type="image" src="/images/edit.gif" onclick="addressEdit('#i'); return false;" title="Edit" />
}
When the user clicks on the edit button I call javascript addressEdit and pass it the index of the selected address.
<script type="text/javascript">
function addressEdit(index) {
$('#FName').val('#Model.Addresses[index].FName');
$('#Addr1').val('#Model.Addresses[index].Company');
...
}
</script>
The problem is on the jQuery lines $('#FName').val('#Model.Addresses[index].FName'); Variable index is underlined in red in VS2012 with message "the name 'index' does not exist in the current context".
How do you pass the value on 'index' to extract the data I need?
Wrap your elements in a spans with some class name. Wrap everything in the loop a div too. I am also removing the onclick method from the markup because we will do it in the unobtrusive way.
#for (int i = 0; i < Model.Addresses.Count; i++)
{
<div class='entry'>
<span class='spanAddress'> #Model.Addresses[i].Company </span>
<span class='spanFName'> #Model.Addresses[i].FName </span>
<img src="/images/edit.gif" class='editLink' />
</div>
}
Now in your javascript
$(function(){
$(".editLink").click(function(e){
e.preventDefault();
var _this=$(this);
var fname=_this.closest("div.entry").find(".spanFName").html();
var add=_this.closest("div.entry").find(".spanAddress").html();
$('#FName').val(fname);
$('#Address').val(add);
});
});
Well, this is client side code remember. So the best place to look is what is generated client side. This means commenting out your javascript event and looking at what is actually rendered to get an idea of what is going on.
When you do that, you will see that the helper autogenerates the names and ids based on your models names. Keep in mind that the name attribute on the inputs is what allows for model binding on post.
So, with all of that in consideration, I would assume it would be something along these lines:
function addressEdit(index) {
$('#FName').val($("#Addresses_"+index+"__FName").val());
//..etc
}

can we pass entire model to javascript asp.net mvc

I have a problem that on javascript call for the form submit , the model gets updated from controller ,but it is not updating in the view. I am thinking to update the model to new model values in javascript . so that the view shows the latest model values
can that be done?
thanks,
michael
Your question is extremely unclear and you provided no source code which makes things even more unclear. From the various comments you may have posted I assume that you are trying to update some model value inside the POST action without removing it from the model state and when the same view is rendered again the old values are displayed.
So I suppose you have a view model that looks something close to this:
public class MyViewModel
{
public HttpPostedFileBase File { get; set; }
public string SomeValue { get; set; }
}
and a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
SomeValue = "initial value"
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// Notice how the SomeValue property is removed from the
// model state because we are updating its value and so that
// html helpers don't use the old value
ModelState.Remove("SomeValue");
model.SomeValue = "some new value";
return View(model);
}
}
and a view:
<% using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) { %>
<div>
<%= Html.LabelFor(x => x.SomeValue) %>
<%= Html.EditorFor(x => x.SomeValue) %>
</div>
<div>
<label for="file">Attachment</label>
<input type="file" name="file" />
</div>
<input type="submit" value="OK" />
<% } %>

Categories

Resources