In my main INV_Assets controller of my MVC5 app, I have an method for Edit() which passes several populated SelectLists() via the ViewBag to allow users to select from all available entities for the relevant list in the other tables of my Database -- Note, if there is a better practice than passing this through the ViewBag, please feel free to guide me to a better way.
// GET: INV_Assets/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
INV_Assets iNV_Assets = await db.INV_Assets.FindAsync(id);
if (iNV_Assets == null)
{
return HttpNotFound();
}
ViewBag.Location_Id = new SelectList(db.INV_Locations, "Id", "location_dept", iNV_Assets.Location_Id);
ViewBag.Manufacturer_Id = new SelectList(db.INV_Manufacturers, "Id", "manufacturer_description", iNV_Assets.Manufacturer_Id);
ViewBag.Model_Id = new SelectList(db.INV_Models, "Id", "model_description", iNV_Assets.Model_Id);
ViewBag.Status_Id = new SelectList(db.INV_Statuses, "Id", "status_description", iNV_Assets.Status_Id);
ViewBag.Type_Id = new SelectList(db.INV_Types, "Id", "type_description", iNV_Assets.Type_Id);
ViewBag.Vendor_Id = new SelectList(db.INV_Vendors, "Id", "vendor_name", iNV_Assets.Vendor_Id);
return View(iNV_Assets);
}
My lists currently populate fine, but for ease of use I want to insert a value of "Add New" into each list, that when clicked will open pop-up (partial view?) of my relevant Create() View for the relevant entity. For example, if the Locations SelectList() has "Add New" clicked, I want to open my Create view for Locations.
Can anyone offer an example of how to do this?
I've been looking for how to insert a new value into the SelectList() but most of what I seem to be coming across is using the example of forgoing the SelectList() instead for an Html.DropDownList(), though I'm not sure why?
The SelectList class inherits IEnumerable<SelectListItem>, which are used to populate drop down lists.
Given a ViewModel object that has the following property:
public SelectList Options
{
get
{
var items = Enumerable.Range(0, 100).Select((value, index) => new { value, index });
SelectList s = new SelectList(items, "index", "value");
return s;
}
}
public int SelectedOption { get; set; }
The view:
#Html.DropDownListFor(m => m.SelectedOption, Model.Options, "Add New", new { #class = "form-control" })
In order to do what you want regarding the popup, you probably need some javascript to deal with this.
If you don't want the "Add New" in the DropDownListFor() you would need to add it manually to your collection before returning it to the view.
Hope this helps.
Related
I have two tables tblProduct & tblImages. tblImages will have multiple images for a product and has a foreign key related to tblProduct. I have a problem with inserting data into multiple tables.
This is my view code:
<!-- Text Boxes and dropdown lists for tblProduct above and below is for adding files to tblImages-->
<div class="col-md-10">
<input multiple type="file" id="file" name="file" />
</div>
and here is my controller's code:
public ActionResult AddProduct_Post([Bind(Include = "productName, productDescription, productPrice, productCategory")]tblProduct tblProduct,List<HttpPostedFileBase> file)
{
List<tblImage> prodImages = new List<tblImage>();
var path = "";
foreach (var item in file)
{
if (item != null)
{
tblImage img = new tblImage();
img.ImageFile = new byte[item.ContentLength];
img.ImageName = string.Format(#"{0}.JPG", Guid.NewGuid());
img.vend_ID = Convert.ToInt32(Session["userID"]);
item.InputStream.Read(img.ImageFile, 0, item.ContentLength);
path = Path.Combine(Server.MapPath("~/Content/img"), img.ImageName);
item.SaveAs(path);
prodImages.Add(img);
}
}
tblProduct.venodrID = Convert.ToInt32(Session["userID"]);
tblProduct.tblImages = prodImages;
if (ModelState.IsValid)
{
db.tblProducts.Add(tblProduct);
db.SaveChanges();
int latestProdID = tblProduct.productID;
foreach (tblImage tblImg in tblProduct.tblImages)
{
tblImg.prod_ID = latestProdID;
db.Entry(tblImg).State = EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("DashBoard");
}
ViewBag.productCategory = new SelectList(db.tblCategories, "categoryID", "categoryName");
ViewBag.vendorGender = new SelectList(db.tblGenders, "genderId", "genderName");
return View();
}
I put a breakpoint on ModelState.IsValid and it is not going inside the if conditions and is returning back the same view without posting the data. Kindly tell me how to solve this issue
P.S: I am new to ASP.NET MVC
[Bind(Include =
you can the check parameter you bind in action method is similar what you defined in the View else you can remove the bind attribute and try this will help you to find what actually error is..
forgive me I am just learning mvc. I have an application that manages projects and utilities. For each project, there can be multiple utilities. There is a "Projects" page that lists all of the projects, and if you click on a Project, it lists all of the utilities associated with it. There is also a button on the project screen to allow you to add Utilities to that project. So, when you click on the project and then click the "Add Utility" button, it pulls up a form to allow you to add a utility to that project. The form has the project ID, utility ID and owner pre-filled, taken from the project controller information. What I am trying to do is set a default on one of the fields in the Utility (relocation expense) to 0.00. So, that, if it is not changed by the user, it shows as 0.00 in the database. Seems simple, right?
Here is my code in the controller currently for the Get method of the Utility (advice from a previous thread) and what I changed it to.
Before:
// GET: /Utility/Create
public ActionResult Create(int? ProjectID)
{
CreateDropDownListForCreateOrEdit(ProjectID);
return View();
}
After:
public ActionResult Create(int? ProjectID)
{
CreateDropDownListForCreateOrEdit(ProjectID);
// initialize the model and set its properties
UtilityDTO model = new UtilityDTO
{
Est_Relocation_Expense = 0M
};
// return the model
return View(model);
}
My view looks like this:
#Html.TextBoxFor(model => model.Est_Relocation_Expense, "{0:0.00}")
This works great...it adds the default value to the field...however, it loses the pre-filled project id, utility id, and owner information (does not pre-fill) that it retrieved from the project controller.
Does anyone know what might be wrong here? I can provide other code from the controller as well, if needed, but it is very long so not sure what else to post.
Added view for project id:
<div class="form-group">
#Html.LabelFor(model => model.Project_ID, new { #class = "control-label col-md-2 CreateEditFieldNamesSpan" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Project_ID, (SelectList)ViewBag.VBProjectIDAndName, "---Select Project---")
#Html.ValidationMessageFor(model => model.Project_ID)
</div>
</div>
You need to set the value of the properties in the model before you pass the model to the view. Your currently only setting at value for Est_Relocation_Expense. If you want the dropdownlist to display the option associated with the ProjectID parameter in your method, then modify your method to
public ActionResult Create(int? ProjectID)
{
CreateDropDownListForCreateOrEdit(ProjectID);
UtilityDTO model = new UtilityDTO
{
Project_ID = ProjectID, // add this
Est_Relocation_Expense = 0M
};
return View(model);
}
Side note: It is not necessary to send the value of ProjectID to the CreateDropDownListForCreateOrEdit() method. From your now deleted code, that was being used only to set the selectedValue property of SelectList which is ignored when binding a dropdownlist to a property. You need only use the constructor which is public SelectList(IEnumerable items, string dataValueField, string dataTextField)
Here is the part of the UI that I'm trying to update:
<label>Country</label>
<select name="country" data-bind="options: $parent.CountryList, optionsCaption: '- Select -'"></select>
As you can see, I tried $parent.CountryList because I was hoping that would refer to the CountryList in the code behind. Here is a snippet of the Page_Load function where I'm storing data from a database into a list of countries:
using (CCGEntities db = new CCGEntities())
{
List<Country> CountryList = db.Countries.ToList();
}
The goal is to take the list of countries and have them populate the select element as a dropdown menu. I tried mimicking the binding for asp:DropDownList but the code behind didn't pick up on an ID attribute for the select element. Would I be better of doing this with asp:DropDownList?
That is not how you must do it in ASP.NET. You must create ViewModels and bind them using ko.applybindings(viewModel, YOUR_HTML_ELEMENT_ROOT). In order to do that, the model should either:
a) Be serialized at run time by the server and dumped into a javascript variable
or b) Fetched dynamically with javascript and then apply the binding
A complete example of how to achieve this with Entity Framework, ASP.NET and Knockout is available here.
Dropdownlist population with knockout.js can seem a bit tricky at first. I ve implemented a knockout binder to make this easier:
ko.extenders.autoOptions = function (target, type) {
target["Options"] = [];
console.log("getting options for type: " + type);
target.Options = ApplicationGateway.getOptions([ApplicationName.Api.Options]+type);
return target;
};
This binder can be used in the following manner in your javascript models:
self.Gender = ko.observable().extend({ autoOptions: 'GENDER', required: { message: 'Gender is required' } });
Which results in the following template usage:
<select data-bind="options: Gender.Options,
value: Gender,optionsText: 'Text',optionsValue: 'Value'">
</select>
My Asp.Net Web API Options Controller looks like this:
public class OptionsController : ApiController
{
private ResourceManager _resourceManager;
private CultureInfo _cultureInfo;
[HttpGet]
[Route("api/Options/{type}")]
public List<ListItem> List(string type)
{
_resourceManager = new ResourceManager("Application.Resources.RESOURCE", typeof(APPLICATION).Assembly);
_cultureInfo = new CultureInfo(Application.CurrentSession.User.LanguageSelected);
switch (type.ToUpper())
{
case "GENDER": return Gender();
...
}
return new List<ListItem>();
}
private List<ListItem> Gender()
{
var items = new List<ListItem>
{
new ListItem(_resourceManager.GetString("Label_Gender_Male", _cultureInfo),Domain.Enums.Gender.Male.ToString()),
new ListItem(_resourceManager.GetString("Label_Gender_Female", _cultureInfo), Domain.Enums.Gender.Female.ToString()),
};
return items;
}
}
I want to do the menu page in a MVC project, there I need to populate some GridViews with different data from some models. First I created some datasets which contain the datatables; in the controller i call the index view which shows the main page.
public ActionResult Index()
{
..........
return View();
}
Index view
#{ Layout = "~/Views/Shared/_mainLayout.cshtml"; }
#{Html.RenderPartial("TicketsPartial");}
#Html.DevExpress().PageControl(s =>
{
s.Name = "tabcontrol";
s.TabPages.Add(tabPage =>
{
tabPage.Text = "Inbox";
tabPage.SetContent(() =>
{
Html.RenderPartial("InboxPartial");
});
});
s.TabPages.Add(tabPage =>
{
tabPage.Text = "Sent";
tabPage.SetContent(() =>
{
Html.RenderPartial("SentPartial");
});
});
}).GetHtml()
So I'm trying to use the Html.RenderPartial to call some partial views... here's the code in InboxPartial
#model DataModels.Email.DS_EmailMessages.DT_com_mail_messagesDataTable
#Html.DevExpress().GridView(s =>
{
s.Name = "Inbox";
s.KeyFieldName = "idticket";
s.Width = System.Web.UI.WebControls.Unit.Percentage(100);
}).Bind(Model).GetHtml()
So first I give the model to the view... the datatable from which the data should be loaded and I bind it to the gridview...
The thing is that this isn't displaying any data and also any column...and I really can't understand why... for example if I give the datatabel as a parameter in the controller like this:
public ActionResult Index()
{
..........
return View(dS_Tickets.DT_com_consultant_tickets);
}
And i erase the model from the views so there will not be any conflict, each partialview will show the columns and data taken from the datatabel, but only from that one table that I gave as a parameter.. I need to take the data from different tables... how can I do this?
Note: I'm using an extension called DevExpress v.12
seems like I got a trouble when I am using MVCContrib.
I am using MVC4 to build a website and I want to show a datagrid that shows all the users
My data model is build by ADO.NET Entity Data Model, but I modify it so that I can use it easily in MVC4.
When I am trying to implement paging function, it throw an error: "The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'. "
source error is on: #Html.Grid(Model).Sort(ViewBag.SortModel as GridSortOptions).Columns(column =>
I have no idea how to fix this issue. in this case, if I am just using sorting, there is no problem. the issue only appears when I add paging function into the website (PS: I have tried only use paging, but it still giving me the same error).
Please help me :)
On the controller:
public ActionResult Index(int? page, GridSortOptions SortModel)
{
userRsy = new UserRepository();
if (CookieUserName == "")
{
return RedirectToAction("Index", "Home");
}
else
{
DBEntities _db = new DBEntities();
//ViewData.Model = _db.Users;
ViewBag.SortModel = SortModel;
IEnumerable<User> userList = _db.Users;
if (!string.IsNullOrEmpty(SortModel.Column))
{
userList = userList.OrderBy(SortModel.Column, SortModel.Direction);
//userList = userList.OrderBy(u => u.UserName);
}
//find login user
var _user = userRsy.Find(CookieUserName);
//ViewBag.Title = _user.FirstName + ", Welcom to E-Tabs Dashboard Management Center";
//Check user admin level
ViewBag.User = _user.FirstName;
ViewBag.Account = _user.UserName;
ViewBag.IsAdmin = false;
if (userRsy.AdminCheck(_user.UserName) == 99)
{ ViewBag.IsAdmin = true; }
//Pagination
userList = userList.AsPagination(page ??1,5);
//show view
return View(userList);
}
}
on the cshtml file:
#model IPagination<E_Tabs_Generic_Portal.Models.User>
#using MvcContrib.UI.Grid;
#using MvcContrib.Pagination;
#using MvcContrib.UI.Pager;
#using MvcContrib.Sorting;
#{
ViewBag.Title = "User";
Layout = "~/Views/Shared/_HomeLayout.cshtml";
}
<div class="content-1">
<h2>User List</h2>
#Html.Grid(Model).Sort(ViewBag.SortModel as GridSortOptions).Columns(column =>
{
column.For(p => p.UserName).Named("User Name");
column.For(p => p.IsEnabled).Named("Enabled");
column.For(p => p.FirstName).Named("First Name");
column.For(p => p.LastName).Named("Last Name");
column.For(p => p.Email).Named("E-Mail");
column.For(p => p.Company).Named("Company");
column.For(p => p.ServerName).Named("On Server #");
column.For(p => p.LastLoginTime).Named("Last Login").Format("{0:yyyy/MM/dd HH:mm}");
}
).Attributes( #class=>"Grid",#width =>"100%", #border =>"1", #style =>"text-align:center;border-collapse:collapse")
#Html.Pager(Model).First("First").Next(">>").Previous("<<").Last("Last").Format("Total{2}, Current{0}-{1} ")
</div>
I had similar problem when I was trying MVCCONTRIB grid first time last month. I fixed it by assigning Ipagination result to another variable and returning it as View.
something like this -
var temp = userList.AsPagination(page ?? 1, 5);
return View( temp);