Persist ID throughout ASP.NET MVC Views - asp.net-mvc

Basically I have an Image Upload controller, that I am inserting in pages as follows :-
<div id='imageList'>
<h2>Upload Image(s)</h2>
#{
if (Model != null)
{
Html.RenderPartial("~/Views/File/ImageUpload.cshtml", new MvcCommons.ViewModels.ImageModel(Model.Project.ProjectID));
}
else
{
Html.RenderPartial("~/Views/File/ImageUpload.cshtml", new MvcCommons.ViewModels.ImageModel(0));
}
}
</div>
So I am passing an ID to the ImageUpload, in this case the ProjectID, so that I can include it in my insert.
Now this is piece of code is populating an ImageModel(id), in my case its ProjectID :-
public ImageModel(int projectId)
{
if (projectId > 0)
{
ProjectID = projectId;
var imageList = unitOfWork.ImageRepository.Get(d => d.ItemID == projectId && d.PageID == 2);
this.AddRange(imageList);
}
}
and this in turn leads to the ImageUploadView.cshtml :-
<table>
#if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>
<img src= "#Url.Content("/Uploads/" + item.FileName)" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
}
</table>
#using (Html.BeginForm("Save", "File", new { ProjectID = Model.ProjectID },
FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" value="submit" /> <br />
<input type="text" name="description" />
}
So far so good, however my problem is that the first time
new { ProjectID = Model.ProjectID }
is correctly populated with the ProjectID, however, when I upload an image, the ProjectID is lost, and becomes zero. Is there a way I can persist the ProjectID for the second time?
Thansk for your help and time.
********* UPDATE *************************
After the upload, the Action is as follows inside the FileController :-
public ActionResult Save(int ProjectID)
{
foreach (string name in Request.Files)
{
var file = Request.Files[name];
string fileName = System.IO.Path.GetFileName(file.FileName);
Image image = new Image(fileName, Request["description"]);
ImageModel model = new ImageModel();
model.Populate();
model.Add(image, file);
}
return RedirectToAction("ImageUpload");
}

You can pass the projectId as a route value from the RedirectToAction. You should change the ImageUpload action to accept the projectId.
public ActionResult Save(int projectId)
{
....
return RedirectToAction("ImageUpload", new { projectId = projectId });
}
public ActionResult ImageUpload(int projectId)
{
var model = .. get the model from db based on projectId
return View("view name", model);
}

Related

MVC 4 Asp.net ,using File Upload code How to save images in Database

here is my view
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table>
<tr>
<td>File :</td>
<td><input type="file" name="File" id="file" /> </td>
</tr>
<tr>
<td><input type="submit" name="submit" value="upload" /></td>
</tr>
Here is my Controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Picture picture)
{
if (picture.File.ContentLength > 0)
{
var fileName = Path.GetFileName(picture.File.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Images"), fileName);
picture.File.SaveAs(path);
}
return RedirectToAction("Index");
}
and Model:
namespace FileUpload.Models
{
public class Picture
{
public HttpPostedFileBase File { get; set; }
}
This code helps me to save image in my MVC project root Image folder , but I want to save it to my database . I have tried many tutorial but could not succeed yet ... '
I am Actually making the student form every student will register his picture.
Convert your image into bytes and then store it in your database
[HttpPost]
public ActionResult Index(Picture picture)
{
byte[] Image;
if (Request.Files["files"] != null)
{
using (var binaryReader = new BinaryReader(Request.Files["file"].InputStream))
{
Image = binaryReader.ReadBytes(Request.Files["files"].ContentLength);
}
Picture.File =Image;
}
return RedirectToAction("Index");
}
Model
public class Picture
{
public byte[] File { get; set; }
}
View For Displaying Image
if (Model.File != null)
{
string imageBase64 = Convert.ToBase64String(Model.File );
string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
<img src="#imageSrc" width="100" height="100" />
}

#Html.DisplayFor() value not change after the postback

#Html.DisplayFor() value not change after send data. I read a article about this issue and say it like this; only send data what such as EditorFor, TextBoxFor, TextAreaFor and change state. Is it true? How can I change this value after the postback?
View
#model HRProj.Model.Person
#using(Html.BeginForm("Skills", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })){
#Html.HiddenFor(m => m.SkillDoc.Filename)
<span class="file-upload">
<span>Choose a file</span>
<input type="file" name="file" />
</span>
File name : #Html.DisplayFor(m => m.SkillDoc.Filename)
<button>Upload</button>
}
Controller
public ActionResult Skills(int? id)
{
Others oparations...
var model = new Person { SkillDoc = db.GetSkillDoc().FirstOrDefault(m => m.PersonId == id) };
return View(model);
}
[HttpPost]
public ActionResult Skills(Person model, HttpPostedFileBase file)
{
Others oparations...
if (ModelState.IsValid)
{
SkillDoc doc = new SkillDoc();
doc.Id = model.SkillDoc.Id;
doc.PersonId = model.SkillDoc.PersonId;
doc.CvDoc = (file != null) ? file.FileName : model.SkillDoc.CvDoc;
db.SkillDocCRUD(doc, "I");
TempData["eState"] = "The record adding successfully";
if (file != null)
{
file.SaveAs(Server.MapPath("~/Files/" + file.FileName));
}
}
return View(model);
}
Please add the following line inside the if block:
model.SkillDoc=doc;
Or rather redirect to Skills action:
return RedirectToAction("Skills", new{id= model.PersonId});

How to create view for given model

I am new to asp .net mvc 4.0. i have given model. i am not getting how can i create view for model. I am facing problem at IList JournalEntries. other entry i am able to do.
public class Journal : BaseClass
{
public virtual string VoucherNo { get; set; }
public virtual DateTime VoucherDate { get; set; }
public string VoucherDateView {
get
{
return VoucherDate.ToShortDateString();
}
}
public IList<JournalEntry> JournalEntries { get; set; }
public IList<Ledger> Accounts { get; set; }
public double TotalAmount
{
get
{
double sum = 0;
if (JournalEntries != null && JournalEntries.Count>0)
foreach (var journal in JournalEntries)
sum = journal.Principal + journal.Interest+sum;
return sum;
}
}
}
I have tried below view but add entry doesn't works.
#model Sms.CoreSociety.Journal
#{
ViewBag.Title = "Create";
}
#{
string data = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
$(document).ready(function () {
$('#document').validate();
$("#VoucherDate").mask("99/99/9999", { placeholder: " " });
function entryVm(entries) {
var self = this;
self.entryList = ko.observableArray(entries);
self.entry = ko.observable();
self.rowClick = function(entry1) {
alert("Delete alert");
self.dispatchList.remove(entry1);
};
self.addEntry = function() {
alert("Add alert");
this.entryList.push({ AccountName_AccountHead: "", DebitCredit: "", Principal: "0.0", Interest: "0.0", Narration: ""});
};
}
var models = #Html.Raw(Json.Encode(Model.JournalEntries)) ;
ko.applyBindings(new entryVm(models));
});
</script>
#using (Html.BeginForm(null, null, FormMethod.Post, new Dictionary<string, object>() { { "class", "form-horizontal" }, { "id", "document" } }))
{
#Html.ValidationSummary(true)
<fieldset>
<div class="row">
<div class="span1">
<label>Voucher No</label>
</div>
<div class="span5">
#Html.DisplayFor(model => model.VoucherNo)
</div>
</div>
<div class="row">
<div class="span1">
<label>Voucher Date</label>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.VoucherDate, "{0:dd/MM/yyyy}", new Dictionary<string, object>() { { "class", "required" } })
</div>
</div>
<div class="row">
<div class="span1">
<label>Amount</label>
</div>
<div class="span5">
#Html.DisplayFor(model => model.TotalAmount)
</div>
</div>
<input type="submit" value="Save" class="btn" id="submit"/>
#if (Model.Id != new Guid())
{
<div style="float: right">
<a class="btn btn-danger" href='#Url.Action("Delete")/#Model.Id' aria-hidden="true">Delete</a>
</div>
}
</fieldset>
}
<h4>Journal Entry</h4>
<p >Entry for<span data-bind="text: entryList().length"> </span> entry(s)</p>
<button data-bind="click: addEntry" class="btn">Add Record</button>
<table>
<tbody data-bind="template: { name: 'entryRowTemplate', foreach: entryList }"></tbody>
</table>
<script type="text/html" id="entryRowTemplate">
<tr>
<td>AccountName_AccountHead: \$ <input data-bind="value: AccountName.AccountHead"/> </td>
<td>DebitCredit: \$ <input data-bind="value: DebitCredit"/></td>
<td>Principal: \$ <input data-bind="value: Principal"/></td>
<td>Interest: \$ <input data-bind="value: Interest"/></td>
<td>Narration: \$ <input data-bind="value: Narration"/></td>
<td>Delete</td>
</tr>
</script>
below is my Journal controller
using System;
using System.Linq;
using System.Web.Mvc;
using Sms.CoreSociety;
using System.Collections.Generic;
namespace SmsModernUI.Controllers
{
public class JournalController : BaseController
{
//
// GET: /AccountGroup/
public ActionResult Index()
{
var journals = Repository.GetAll<Journal>().OrderBy(x => x.VoucherNo);
return View(journals);
}
public ActionResult Create(Guid id)
{
if (id == new Guid())
{
var journal = new Journal();
string lastvoucherno = Repository.GetAll<Journal>().OrderBy(x => x.VoucherNo).Last().VoucherNo;
journal.VoucherNo = (int.Parse(lastvoucherno) + 1).ToString();
journal.VoucherDate = System.DateTime.Now;
journal.JournalEntries = new List<JournalEntry>();
journal.Accounts = Repository.GetAll<Ledger>();
return PartialView(journal);
}
var journal1 = Repository.Get<Journal>(id);
journal1.JournalEntries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == id);
journal1.Accounts = Repository.GetAll<Ledger>();
return PartialView(journal1);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Journal journal)
{
if (journal.Id == new Guid())
{
var jj = Repository.Save(journal);
foreach (var journalentry in journal.JournalEntries)
{
journalentry.Id = jj.Id;
Repository.Save(journalentry);
}
}
else
{
Journal jr = Repository.Get<Journal>(journal.Id);
var entries = Repository.GetAll<JournalEntry>(x=>x.Journal.Id == journal.Id);
foreach (var entry in entries)
{
Repository.Delete(entry);
}
var jj = Repository.Save(journal);
foreach (var journalentry in journal.JournalEntries)
{
journalentry.Id = jj.Id;
Repository.Save(journalentry);
}
}
return RedirectToAction("Index");
}
public ActionResult Index1()
{
Journal journal1 = Repository.Get<Journal>(new Guid("7A6EEBBC-2F3A-4A27-ACF8-A1D40115A68F"));
journal1.JournalEntries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == journal1.Id);
journal1.Accounts = Repository.GetAll<Ledger>();
return View(journal1);
}
public ActionResult Delete(Guid id)
{
Journal jr = Repository.Get<Journal>(id);
var entries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == jr.Id);
foreach (var entry in entries)
{
Repository.Delete(entry);
}
var result = Repository.Delete(jr);
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult Create1(Journal journal)
{
var temp = journal;
return RedirectToAction("Create",journal.Id);
}
}
}
Views are not genereted from models. You need Controller Action method to pass your model to View.
public ActionResult()
{
var model = new Journal
{
//**define here value of model's properties, that you need in View
}
return View(model);
}
EDITED: After your addition.
I would devide it into two parts. Create ViewModel and pass it from View To Controller.
public JurnalViewModel
{
public Journal journal {get; set;}
public IList<JournalEntry> JournalEntries {get; set;}
}
Than in Create action first create journal and after foreach JournalEntries in model create new JournalEntry.
EDITED 2 To your comment. Quick sample:
[HttpPost]
public ActionResult Create (JurnalViewModel model)
{
var journal = new Journal();
db.Journals.Add(journal);
journal.name = model.journal.name
.....
//**some code
db.SaveChanges()
foreach(var item in model.JournalEntries )
{
var entry = new JournalEntry()
db.JournalEntries .Add(entry);
entry.property = item.property;
....
//**some code
db.SaveChanges()
}
}
Your problem is that you have no class constructor for JournalEntries.
public Journal()
{
JournalEntries = new List<JournalEntry>();
Accounts = new List<Ledger>();
}
Right click to your Action method inside controller and click add view then check create strongly typed-view checkbox then choose your desired model from dropdown in displayed dialogue box

show data from viewmodel in view

I tried this code but I have error like this:
The model item passed into the dictionary is of type
'System.Collections.Generic.List`1[XNet.Repository.Model.RoomType]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[XNet.Repository.Model.EditRoomTypeViewModel]'.
I don't know, whats part give an error. Please help.
my service
public List<EditRoomTypeViewModel> GetViewRoom(int RoomTypeID)
{
List<RoomType> roomTypes = (from d in _RoomTypeRepository.All()
select d).ToList();
List<EditRoomTypeViewModel> editRoomTypeViewModel = new List<EditRoomTypeViewModel>();
foreach (RoomType roomType in roomTypes)
{
editRoomTypeViewModel.Add(new EditRoomTypeViewModel
{
RoomTypeID = RoomTypeID,
RoomTypeName = roomType.RoomtypeName,
RoomTypeDescription = roomType.RoomTypeDescripton,
});
}
return editRoomTypeViewModel;
}
my controller
public ActionResult Room()
{
ViewBag.hotel = _hotelService.GetByID(2).HotelName;
List<EditRoomTypeViewModel> editRoomTypeViewModel = _roomViewService.GetViewRoom(_HotelID);
return View(editRoomTypeViewModel.FirstOrDefault());
}
my view model
public class EditRoomTypeViewModel
{
public int RoomTypeID { get; set; }
public string RoomTypeName { get; set; }
public string RoomTypeDescription { get; set; }
}
my view
#model IEnumerable<XNet.Repository.Model.EditRoomTypeViewModel>
#{
ViewBag.Title = "Room";
}
<h2>Room</h2>
<div>
#Html.Label("Hotel Name");
</div>
<div>
#ViewBag.hotel
</div>
<table>
#foreach (var a in Model)
{
<tr>
<td>
#Html.DisplayFor(model => a.RoomTypeName)
</td>
<td>
<input style="width:100px;" type="button" title="EditRoomType" value="Edit" onclick="location.href='#Url.Action("EditRoom", "Hotel", new { RoomTypeID = a.RoomTypeID})'" />
</td>
</tr>
}
</table>
<input style="width:200px;" type="button" title="EditRoomType" value="New Room Type" onclick="location.href='#Url.Action("NewRoom", "Hotel") '" />
I noticed that you returned just one editRoomTypeViewModel object in your controller, but in your view you declared the model as IEnumerable<XNet.Repository.Model.EditRoomTypeViewModel>.
Another point is that the error seems to be related to an assignment of ViewBag somewhere else, cause it contains thisdictionaryrequires a model item of type and probablt the only thing that is of type dictionary is ViewBag.
Just remove the .FirstOrDefault() in the controller action and you should be good to go.
public ActionResult Room()
{
ViewBag.hotel = _hotelService.GetByID(2).HotelName;
List<EditRoomTypeViewModel> editRoomTypeViewModel = _roomViewService.GetViewRoom(_HotelID);
return View(editRoomTypeViewModel);
}

I cannot get just the selected values from dropdownlists in my view back in my controller

I hava a view where I have a list of links, being each link a region where the companies has offices.
Everytime I select a region, I get a list of processes. For every process, I get a dropdowlist from where to choose a owner of the process and a list of checkboxs of tests to choose.
In my controller, I get string[] OwnerId as the values selected in the dropdowlists.
The thing is, I get all values from all dropdowlists, not just those that were selected. How can I get just the ones I selected??
This is my view
#using CTTModel
#using TestingTool.ViewModels
#model TestRunModel
#{
ViewBag.Title = "Create";
}
<h2>
Create</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>Regions</legend>
#foreach (Region region in Model.Regions)
{
#Html.ActionLink(#region.Name, "Create", new { id = region.Id })<br />
}
<div class="editor-field">
#foreach (ProcessModel process in Model.Processes)
{
<h1>#process.Name</h1>
**List<User> users = ViewBag.Users;
<select id="OwnerId" name="OwnerId" >
#foreach (User user in users)
{
<option value="#user.Id">#user.Name</option>
}
</select>**
<table>
<tr>
#{
int cnt = 0;
foreach (TestModel testModel in process.Tests)
{
if (cnt++ % 3 == 0)
{
#: </tr> <tr>
}
#: <td>
<input type="checkbox"
name="selectedTests"
value="#testModel.Id/#testModel.ProcessId/#testModel.RegionId"
#(Html.Raw(testModel.Active ? "checked=\"checked\"" : "")) />
#testModel.Name #:: #testModel.Description
#:</td>
}
#: </tr>
}
</table>
}
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<fieldset>
<legend>Test Screen</legend>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
And this is my controller. The Create Post does nothing yet, I'm trying to get the right values first.
//
// GET: /TestPreparation/Create
public ActionResult Create(int id = 1)
{
TestRunModel testRunModel = new TestRunModel();
foreach (Region region in _db.Regions)
{
testRunModel.Regions.Add(region);
}
TestRun testRun = _db.TestRuns.OrderByDescending(x => x.Id).First();
foreach (TestRunProcessRegion region in testRun.GetProcessesForRegion(_db.Regions.Single(i => i.Id == id)))
{
ProcessModel process = new ProcessModel
{
Code = region.ProcessRegion.Process.Code,
Description = region.ProcessRegion.Process.Description,
Name = region.ProcessRegion.Process.Name,
Process = region.ProcessRegion.Process.Id
};
foreach (SubProcess subProcess in region.ProcessRegion.Process.SubProcesses)
{
foreach (Risk risk in subProcess.Risks)
{
foreach (Test test in risk.Tests)
{
TestModel testModel = new TestModel
{
Id = test.Id,
Name = test.Name,
Description = test.Description,
ProcessId = region.ProcessRegion.Process.Id,
RegionId = region.ProcessRegion.Id
};
process.Tests.Add(testModel);
}
}
}
testRunModel.Processes.Add(process);
}
var users = new List<User>();
foreach (User user in _db.Users)
{
users.Add(new User
{
Id = user.Id,
Name = user.Name,
});
}
ViewBag.Users = users;
return View(testRunModel);
}
//
// POST: /TestPreparation/Create
[HttpPost]
public ActionResult Create(string[] OwnerId, string[] selectedTests, string[] processes)
{
if (ModelState.IsValid)
{
//_db.TestRunStatus.Add(testrunstatus);
//_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
The reason why you are not getting any data back is because the method signature of your Post Action needs to be
public ActionResult Create(string OwnerId ...) //preferably int depending on what OwnerId is
This is because you only select one item out of the drop down box. So if you use this signature as opposed to string[], the Model binder will pass the selected value back to your action.
Having said this, it is better practice and the "MVC Way" to use,
Html.DropDownFor(x => x.UserID) it really makes things easier :)
This applies to all html input controls:
http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/examining-the-edit-methods-and-edit-view
UPDATE
I think the best thing to do would be to add an OwnerID to the ProccessModel class.
Becuase ProccessModel looks to be IEnumberable<ProccessModel> Processes contained in the ViewModel you can get the Model to Bind in the following way using the defult MVC model binder.
Phil Haack has bloged about binding to lists here:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Adapting from Phil's post I think you will have to do something like this:
<% for (int i = 0; i < Model.Processes.Count; i++) { %>
<%: Html.SelectListFor(model => model.Processes[i].OwnerID, (IEnumerable<SelectListItem>)ViewBag.Users) %>
<% } %>
Change the ViewBag.User to:
var users = _db.Users.Select(x => new SelectListItem(){
text = x.Name,
value = x.Value
});
Modify the Post Action:
[HttpPost]
public ActionResult Create(TestRunModel model)
{
foreach(var process in model.Porcesses)
{
process.OwnerID // This should be a user selected value
}
// code removed for brevity
}
I could help with getting the TestModel values if you like but I need to do some work now ;)

Resources