ASP.NET MVC using more than 1 DataContext Insert Method - c#

So i recently want to try using more than 1 database
my main problem is the attribute on 1st and 2nd entities is different, so for example in 1st entities sample_table1 contain: "member_id" and "member_code" and the 2nd entities sample_table_2 contain "student_id" and "student_code" it's just the naming, the value of the attribute is same, so member_id = student_id, member_code = student_code
Example:
Controller
private MyEntities db = new MyEntities ();
//not sure know by add this one, my controller can connect 2 database, but the intellisense is working when i'm using db2 class
private MyEntities2 db2 = new MyEntities2 ();
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateSomething(sample_table1 sample_table1, sample_table2 sample_table2)
{
if (ModelState.IsValid)
{
//insert data to 1st Entities
db.sample_table1.Add(sample_table1);
db.SaveChanges();
//insert data to 2nd Entities
"???" // because the attribute name on 2nd entities is not the same as the 1st entities, i cannot using either sample_table1 & sample_table2
db2.SaveChanges();
}
}
Views
#model 1st_entites_data_model.Models.sample_table1
// i don't know for sure but the 2nd entities data model won't appear when i add view
#{
ViewBag.Title = "Create Something";
}
#using (Html.BeginForm("CreateSomething", "test", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
//i'm using only the 1st entities, because there is no need for user input the same data value twice
#Html.TextBoxFor(model => model.sample_table1.member_id)
#Html.ValidationMessageFor(model => model.sample_table1.member_id)
#Html.TextBoxFor(model => model.sample_table1.member_code)
#Html.ValidationMessageFor(model => model.sample_table1.member_code)
}
i cannot change the 2nd entities name because somebody else is making the 2nd entities, and i cannot edit the database structure...
Thank You Very Much...

You can use automapper to transfer data from first to second entity.After that your code will be:
...
db.sample_table1.Add(sample_table1);
db.SaveChanges();
//insert data to 2nd Entities
var sample_table2 = Mapper.Map<sample_table2>(sample_table1);
db2.sample_table_2.Add(sample_table2);
db2.SaveChanges();
...

Related

Getting the selected value from a DropDownListFor using a ViewBag list

I'm having trouble getting the data from a DropDownListFor using a ViewBag list with my model. Here is my Controller code:
[HttpGet]
public ActionResult JoinTeam()
{
var TeamList = _db.TeamModels.ToList();
SelectList list = new SelectList(TeamList, "Id", "TeamName");
ViewBag.TeamList = list;
return View();
}
And the Razor view form looks like this:
#using (Html.BeginForm("JoinTeam", "Home", FormMethod.Post))
{
#Html.TextBoxFor(m => m.DisplayName, new { #class = "form-control form-control-lg", placeholder = "Enter your Battle Net ID" })
<br/>
#Html.DropDownListFor(m => m.TeamModel, (SelectList)ViewBag.TeamList, "- Select a Team to Join -", new { #class= "form-control form-control-lg" })
<br />
<button type="submit" class="btn btn-primary" style="width:100%;text-align:center;">Submit</button>
}
The TextBoxFor helper is returning the data correctly, but whatever option I have selected in the drop down does not get passed into my post method. Does anyone have any ideas?
The post action does work as it's getting the data from the model for the TextBoxFor help, but here's what it looks like:
[HttpPost]
public async Task<ActionResult> JoinTeam(GuardianModel model)
{
try
{
string BNETId = model.DisplayName.Replace("#", "%23");
long memberId = 0;
if (ModelState.IsValid)
{
Bungie.Responses.SearchPlayersResponse member = await service.SearchPlayers(MembershipType.Blizzard, BNETId);
memberId = member[0].MembershipId;
}
using (var context = new CoCodbEntities1())
{
var g = new GuardianModel
{
MembershipId = memberId.ToString(),
DisplayName = BNETId,
MembershipType = 4,
TeamID = model.TeamModel.Id
};
TempData["UserMessage"] = ViewBag.TeamList.Id;
return RedirectToAction("Success");
}
}
catch
{
}
return View();
}
These are the values getting passed into the Post action
From the screenshot you shared, it looks like TeamModel property is the virtual navigational property of type TeamModel. You should not bother about loading that. All you need to worry about loading the forign key property value (usually a simple type like an int or so.
Your SELECT element name should be TeamID. When the form is submitted, it will map the selected option value to the TeamID property value of your model which is the foreign key property.
#Html.DropDownListFor(m => m.TeamID, (SelectList)ViewBag.TeamList,
"- Select a Team to Join -", new { #class= "form-control form-control-lg" })
While this might fix the issue, It is a good idea to use a view model instead of using your entity class.
I found the issues I was having. All I needed to get passed into the post action was the Id of the TeamModel. So I changed this line:
#Html.DropDownListFor(m => m.TeamModel.Id, (SelectList)ViewBag.TeamList, "- Select a Team to Join -", new { #class= "form-control form-control-lg" })
I just added the Id and it seemed to work.

razor dropdown list add the data but show after refresh the page

#{
HotelManagementEntities db = new HotelManagementEntities();
var list = db.tblCategories.Select(m => new { m.intseqid, m.varCategory}).ToList();
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
}
#Html.DropDownList("tblCategories",
ViewBag.Category as SelectList,
new
{
#class = "drplist",
id = "drpItemCat",
ng_show = "selectfieldforcat"
})
There are problems in your code, you are populating list from database here:
var list = db.tblCategories.Select(m => new { m.intseqid, m.varCategory}).ToList();
but down in the code when creating SelectList, you are again getting records form the database using the dbContext:
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
// note the db.tblCategories as first parameter, this is wrong
and if you have actually written this code in view, then you don't even need ViewBag, but your approach is not right, you should be writing the poupulation code in the controller action and then use it in the view:
public ActionResult SomeAction()
{
HotelManagementEntities db = new HotelManagementEntities();
ViewBag.Category = new SelectList(db.tblCategories, "intseqid", "varCategory");
}
In Controller:
public ActionResult Add()
{
ViewBag.countryList = GetCountries();
return View();
}
In razor View .csHtml
#Html.DropDownListFor(x => x.countryId, new SelectList(ViewBag.countryList, "id", "Name"), 'Select Country',
new { #id = "ddlCountry", #rows = 1 })
Despite the fact, it's not a good practice to have data retrieval in views, based on you code, you could try the following:
#{
var db = new HotelManagementEntities();
var list = db.tblCategories.Select(m => new
{
m.intseqid,
m.varCategory
}).ToList();
}
#Html.DropDownList("tblCategories", new SelectList(#list, "intseqid", "varCategory"));
A more appropriate approach it would be to create a model, which would contain as a property a SelectList object. Then at the corresponding action at the controller to create a new model and set the categories to mentioned above property. Last pass at your view (so now you have to define that your view expects a model of a specific type, that you declared above) the model and at the dropdownlist html helper do the following:
#Html.DropDownList("tblCategories", Model.Categories)
This way you are more adhered to separation of concerns that is built in the MVC pattern and your code would be more readable and maintainable in the long run. Your example is pretty simple. So that I mentioned before cannot be seen at this point. However, while you model would be more complex and you have to do more things in the views, you will see that I mean by saying more readable and maintainable.
Last but not least, try to avoid using the ViewBag. Apparently you can accomplish what you have to do with the use of ViewBag, but it's far better you pass a strongly typed object as a model to your view and have there all you need to show on the view rather than adding things in the ViewBag at the controller and then use casts in the view to do whatever you want.

Model MVC IEnumerable without Iteration

Rookie Question. So I have a IEnumerable Model And as you can see my question is simple. I just want to get the Value of the First item in the model Without iterating through the whole model.
As this is only one instance to happen. I don't want to itterate from the model just to get 1 Entity from it and I wouldn't also want to rely on the ViewBag or ViewData for this.
Is this possible?
Client = Model.FirstOrDefault().ClientID
Object reference not set to an instance of an object.
I also tried select()
#model IEnumerable<RMQGrainsFinalCement.ModelsCorn.POCorn>
#{
ViewBag.Title = "POIndex";
}
<h2>PO Index</h2>
#Html.ActionLink("Add PO", "Create", "POCorns", new {ClientID = Model.FirstOrDefault().ClientID },null)
To mitigate unexpected errors, do something like this in your view:
#{
var clientId = 0;
if (Model.Any())
{
clientId = Model.First().ClientId;
}
}
#Html.ActionLink("Add PO", "Create", "POCorns", new {ClientID = clientID },null)

How to properly use SelectListItem for HTML.DropDownList instead of SelectList?

I've been digging through other posts trying to figure out how to go from using a SelectList in my controller to fill an #Html.DropDownList in my View to instead use what seems to be the commonly suggested SelectListItem, but I'm completely lost?
I have a main INV_Assets model that when I go to the Edit View, I include Drop Down Lists for other Model Properties (Location, Manufacturer, Model, Status, Type, Vendor, etc.) My current code below adequately fills the lists and allows me on Edit() to change the chosen entity value to any other value stored in that relevant table.
CURRENT CODE:
Controller:
// 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);
}
// POST: INV_Assets/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Id,Model_Id,Manufacturer_Id,Type_Id,Location_Id,Vendor_Id,Status_Id,ip_address,mac_address,note,owner,cost,po_number,description,invoice_number,serial_number,asset_tag_number,acquired_date,disposed_date,created_date,created_by,modified_date,modified_by")] INV_Assets iNV_Assets)
{
if (ModelState.IsValid)
{
db.Entry(iNV_Assets).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
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);
}
View - Just [Locations] for example:
<div class="form-group">
#*#Html.LabelFor(model => model.Location_Id, "Location_Id", htmlAttributes: new { #class = "control-label col-md-2" })*#
<span class="control-label col-md-2">Location:</span>
<div class="col-md-10">
#Html.DropDownList("Location_Id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Location_Id, "", new { #class = "text-danger" })
</div>
</div>
What I'm trying to do now is add a value to each list stating "Add New", which I want to allow users to click on and have a (partial view?) popup for them to immediately add a new relevant record (Ex. New [Location] of "Warehouse 2") and then be able to choose that from the [Locations] list for the particular Asset being Edited.
Can anyone walk me through this?
A lot of the suggestions are to add a SelectList or IEnumerable<SelectListItem> to my relevant Model properties, but from there I am lost on what to tweak in my controller/view? Currently I am using Code-First Migrations with an InventoryTrackerContext.cs inside my DAL folder for the project.
You're confusing two very different aspects of this. First, Html.DropDownList only requires an IEnumerable<SelectListItem>. Passing a full SelectList object satisfies this parameter merely because a SelectList is an IEnumerable<SelectListItem>. The advice to not use SelectList is simply to save yourself the work of having to construct a full SelectList object (and remembering to do things like set the selectedValue to the right item), when Razor will handle this for you. Whether you use SelectList or IEnumerable<SelectListItem> has no bearing on the remainder of your question.
As far as adding items to an existing drop down list goes, you have to use JavaScript for that. At a basic level, it's as simple as just just selecting the select element in the DOM and appending a new option node.

dropdown in mvc3 edit form

This maybe very simple but I cant seem to sort it out on my own.
I have created a simple db and entity modal that looks like this
I am trying to create an Create form that allows me to add a new Order. I have a total of 3 tables so what I am trying to do is have the form allowing the person to enter Order date and also has a dropdown list that allows me to select a product from the product table
I want to be able to create a Add or Edit view that allow me to insert the OrderDate into the OrderTable and also insert the OrderID and selected ProductID into OrderProduct.
What steps do I need to do here.
I have created an OrderController and ticked the "Add Actions" and than added a Create View which looks like this
#model Test.OrderProduct
#{
ViewBag.Title = "Create2";
}
<h2>Create2</h2>
<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()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>OrderProduct</legend>
<div class="editor-label">
#Html.LabelFor(model => model.OrderID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.OrderID)
#Html.ValidationMessageFor(model => model.OrderID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProductID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ProductID)
#Html.ValidationMessageFor(model => model.ProductID)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
This creates the view that contains a textbox for both OrderID and ProductID however no date.
My controller CreatePost hasnt been changed
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
var data = collection;
// TODO: Add insert logic here
// db.Orders.AddObject(collection);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
My questions are,
1.How do I swap out ProductID textbox to be a dropdown which is populated from Product
2.How do I get the data from FormCollection collection? I thought of just a foreach however I dont know how to get the strongly typed name
Any help for a newbie would be very helpful.
Thank you!
First thing's first, don't bind to the Order entity. Never bind to an EF object, always try and use a ViewModel. Makes life simpler for the View, and that is the goal here.
So, have a ViewModel like this:
public class CreateOrderViewModel
{
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
public int SelectedProductId { get; set; }
public IEnumerable<SelectListItem> Products { get; set; }
}
That's it right now.
Return that to your View in your [HttpGet] controller action:
[HttpGet]
public ActionResult Create()
{
var model = new CreateOrderViewModel
{
Products = db.Products
.ToList() // this will fire a query, basically SELECT * FROM Products
.Select(x => new SelectListItem
{
Text = x.ProductName,
Value = x.ProductId
});
};
return View(model);
}
Then to render out the list of Products: (basic HTML excluded)
#model WebApplication.Models.CreateOrderViewModel
#Html.DropDownListFor(model => model.SelectedProductId, Model.Products)
The only thing i don't know how to do is bind to the DateTime field. I'm guessing you would need an extension method (HTML Helper) which renders out a Date Picker or something. For this View (creating a new order), just default to DateTime.Now.
Now, onto the [HttpPost] controller action:
[HttpPost]
public ActionResult Create(CreateOrderViewModel model)
{
try
{
// TODO: this manual stitching should be replaced with AutoMapper
var newOrder = new Order
{
OrderDate = DateTime.Now,
OrderProduct = new OrderProduct
{
ProductId = SelectedProductId
}
};
db.Orders.AddObject(newOrder);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Now, i also think your EF model needs work.
To me (in English terms), a Product can have many orders, and an Order can have many Products.
So, it should be a many-to-many. Currently it's a 1-1 with a redundant join table. Did you generate that from a DB? If so, your DB possibly needs work.
You should have a navigational property called Products on the Order entity, which references a collection of Product, made possible by a silent join to the join table in the many-to-many.
This also means you no longer have a DropDownList, but a MultiSelectDropDownList.
Thanks Craig. Your few days (as at time of posting) of MVC have solved my few days of trying to get the selected value back from DropDownListFor.
I had no problem in the Create view in getting the selected value of the DDLF, but the Edit view was a completely different matter - nothing I tried would get the selected value back in the Post. I noticed the selected value was lurking in the AttemptedValue of the ModelState, and so Dr.Google referred me here.
I had this in my view
#Html.DropDownList(model => model.ContentKeyID, Model.ContentKeys, Model.ContentKeyName)
where ContentKeys is a SelectList populated from the DB via a ViewModel, and ContentKeyName is the curently selected name.
The wierd thing is, I have another DDL on the view populated in an identical manner. This one works. Why, I don't know. It is the second DDL on the form, but I can't see that making a difference.
I read somewhere else it might have been that I was using Guids as the Id, but that didn't seem to make a difference - I changed to Int32, but don't think I had to - I think it's enums that disagree with DDLF. Nullables seemd to make no difference either.
Now that I've added the form collection to my Post ActionResult, and get the selected value using
-view
#Html.DropDownList("ContentKey", Model.ContentKeys)
-in controller (Post)
contentKeyId = int.Parse(form.GetValue("ContentKey").AttemptedValue);
all is good, and I can get on with more exciting things. Why is that the simplest things can hold you up for so long?
I have been struggling with this over the last day or so too. I'll share my limited knowledge in the hope that it will help someone else.
Note that I use a singleton with a pre-populated list to keep my example application small (i.e. no EF or DB interaction).
To show the ProductList you will need to have a ViewBag or ViewData item which contains the ProductList.
You can set this up in the Controller with something like
ViewData["ProductList"] = new SelectList(Models.MVCProduct.Instance.ProductList, "Id", "Name", 1);
Then update your View to something like:
<div class="editor-field">#Html.DropDownList("ProductList")</div>
For the Post/Create/Update step you need to look into the FormCollection to get your results. Reading other posts it sounds like there used to be a bug in here, but it's fixed now so ensure you have the latest. For my example I have a DropDownList for Product so I just get the selected Id and then go searching for that Product in my list.
[HttpPost]
public ActionResult Create(FormCollection form )//Models.MVCOrder newOrder)
{
MVC.Models.MVCOrder ord = Models.MVCOrder.Instance.CreateBlankOrder();
//Update order with simple types (e.g. Quantity)
if (TryUpdateModel<MVC.Models.MVCOrder>(ord, form.ToValueProvider()))
{
ord.Product = Models.MVCProduct.Instance.ProductList.Find(p => p.Id == int.Parse(form.GetValue("ProductList").AttemptedValue));
ord.Attribute = Models.MVCAttribute.Instance.AttributeList.Find(a => a.Id == int.Parse(form.GetValue("attributeId").AttemptedValue));
UpdateModel(ord);
return RedirectToAction("Index");
}
else
{
return View(ord);
}
}
I've only been working on MVC3 for the last few days, so any advice on improving the above would be appreciated.

Categories

Resources