I have a ASP.NET MVC 4 Project, and I need to be able to upload a file or files to save them and make an instance of that file or files( so I will be able to keep information about them).
In order to implement this I have two classes inside of 'Models':
1. UploadFile: (this class will represent a single file)
public class UploadFile
{
public long ID { get; set; }
public string Path { get; set; }
public string Status { get; set; }
public HttpPostedFileBase File { get; set; }
}
2. Scan: (this class will represent a one upload of file or files)
public class Scan
{
public IEnumerable<UploadFile> Files { get; set; }
public long ContentLength()
{
long size = 0;
foreach (UploadFile f in Files)
{
size =+ f.File.ContentLength;
}
return size;
}
}
also I have one controller 'HomeController.cs", and I have this action in there:
[HttpPost]
public ActionResult Index(Scan scan)
{
if (scan.ContentLength() > 0)
{
foreach (var s in scan.Files)
{
var fileName = Path.GetFileName(s.File.FileName);
var path = Path.Combine(Server.MapPath("~/Content/UploadFiles"), fileName);
s.File.SaveAs(path);
}
}
return RedirectToAction("Index");
}
And the View is 'index.cshtml', and this is the begin.form:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table>
<tr>
<td>File:</td>
<td><input type="file" name="Scan" id="Scan" multiple /></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="submit" value="Upload" /></td>
</tr>
</table>
}
</div>
My Main Goal: upload a file/files (save them at "~/Content/UploadFiles") and during this process to create an instance of UploadFile and Scan (Scan hold a collection of UploadFile), so i can represent them to the user and keep tracking and catalog them in my DB.
My problem is that "scan" is null in 'homecontroller.cs' how can i pass argument so i could create instances of the two classes and still upload the file ?
As you may notice i'm new at MVC design-structure, so if i'm missing a point or two of MVC because of my implement let me know.
Thanks.
Related
I'm really a begginer at programing so ease stuff are hard for me if can anyone explain me or help me in my situation I would apreciate a lot.
On my create method I need to save a file (pdf in db).
What I have now:
Model:
public class Candidate : BaseEntity
{
public int Id { get; set; }
public string Name { get; set; }
public int Number { get; set; }
public string Profile { get; set; }
public Byte[] CV { get; set; }
}
Controller:
[HttpPost("UploadFiles")]
public IActionResult Post(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
// full path to file in temp location
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
using (var stream = new MemoryStream())
{
files.CopyTo(stream);
//await formFile.CopyToAsync(stream);
}
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { count = files.Count, size, filePath });
}
In my view i'm using this to attach the file:
<form method="post" enctype="multipart/form-data" asp-controller="UploadFiles" asp-action="Index">
<div class="form-group">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input type="file" name="files" multiple />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Upload" />
</div>
</div>
</form>
You're not going to get a file path to work with. An uploaded file would be in the HTTP request, but you haven't set your action method up to accept that properly. You really should read some tutorials about how to upload files in ASP.NET MVC so you have the general idea, rather than asking someone on Stack Overflow to explain what you need to do.
#mason.
This is not a complete answer to your problem but it will show you how file uploading works in asp.net mvc. You will have to modify it according to your problem.
Here’s a form that will post back to the current action.
#using (Html.BeginForm("Upload", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
Here’s the action method that this view will post to which saves the file into a directory in the App_Data folder named “uploads”.
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file) {
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
Visit this for complete solution
Again this answer is only to understand how we made HTTP request to upload files and how to save files.
Hello I have functionality to save text and image from forms to Azure SQL db (text) and to Azure Blobs for my images. Also it's hosted in cloud in Azure and saving and uploading works fine. Running on the usual stack C# EF MVC5 Bootstrap Vanilla js and Azure Blobs Webrole etc.
I am stuck on an area I can't seem to figure out - display my view model (this is a viewmodel with two EF objects i.e. two database tables) together with the blob list (Azure blob object). Due to them not being same context types technically is the issue, but how can we combine the two and output like so:
Return View(jobsVModel + Blobs);
Here is my current working:
Model:
namespace client.Models
{
public class JoinUsersandJobsModel : DbContext
{
public tradesusers tradesusers { get; set; }
public jobs jobs { get; set; }
public uploadedfiles uploadedfiles { get; set; }
//add a blob service to our model
//public BlobProfileImageServices _blobServices = new BlobProfileImageServices();
}
}
The I have my Controller:
private traderEntities db = new traderEntities();
BlobProfileImageServices _blobServices = new BlobProfileImageServices();
public ActionResult Index(string usernameCookie)
{
var viewModel = from u in db.tradesusers
join j in db.jobs on u.id equals j.jobbyuserid
join pic in db.uploadedfiles on j.id equals pic.ImageId
where u.email.Equals(usernameCookie)
select new JoinUsersandJobsModel { tradesusers = u, jobs = j, uploadedfiles = pic };
//blob container
List<ImageVM> images;
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
List<string> blobs = new List<string>();
foreach (var blobItem in blobContainer.ListBlobs())
{
blobs.Add(blobItem.Uri.ToString());
}
images = blobs
// convert an Azure blob record into an ImageVM:
.Select(b => new ImageVM()
{
})
.ToList();
//return View(blobs);
//return View(imageModel);
//List<Object> allS = (from x in viewModel select (Object)x).ToList();
//allS.AddRange((from x in blobs select (Object)x).ToList());
return View(images);
//return View(db.tradesusers.ToList());
}
As you can see above I want to return the two objects, one of which is called 'blobs' and the second called 'viewModel' together at the same time to my view but we can see they're are two different object types! 'Return View(viewModel.ToList());' alone works, so does 'Return View(blobs);'.
My View:
#model IEnumerable<traderclient.Models.JoinUsersandJobsModel>
<--!#model2 List<traderclient.Models.ImageVM>-->
#{
ViewBag.Title = "Profile";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>system - Client's Profile</title>
</head>
<body>
<br /><br /><br /><br /><br />
<h1>Profile</h1>
#foreach (var item in Model)
{
<div>
<h5> Profile pic</h5>
<hr />
<dl class="dl-horizontal">
<dt>
Pic
</dt>
<dt>
</dt>
<dd>
<img src="#Url.Content(#item.uploadedfiles.ImagePath+#item.uploadedfiles.ImageName)" width="250" height="250" multiple />
</dd>
</dl>
<p>
#Html.ActionLink("Edit", "Edit", new { id = #item }) |
#Html.ActionLink("Back to List", "Index")
</p>
</div> }
<table>
<tr>
<td>
<table class="table" style="width:200px;">
<tr>
<td style="width:50%"> Image </td>
<td style="width:25%"> Delete </td>
</tr>
<ul style="list-style-type:none; padding:0;">
#foreach (var item in model2)
{
<tr>
<td> <img src="#item." alt="image here is" width="100" height="100" /> </td>
<td> <input type="button" id="#item." onclick="deleteImage('#item');" value="Delete" /></td>
</tr>
}
</ul>
</table>
</td>
<td style="width:100px"></td>
</tr>
</table>
Again above in the View using only ONE Model definition works so i.e. the IEnumerable for the jobs or tradesusers tables or if I ONLY use the List object for the Blob image object that works too. But like the controller I cannot combine the two. As I've previously mentioned the rest of data (all data apart from the blob) all resides in the Azure SQL database. Only the images live in the Azure Blobs.
Don't forget my definition for my Blobs which resides in this project's root too as a separate class:
You shouldn't use your internal objects (be it Microsoft.WindowsAzure.Storage.* objects) or your own database entities) as ViewModels - you should create new ViewModel classes for each logical view component (view, partial, repeated element, etc) and populate them inside your Controller actions with data from your internal objects.
For example, if you have a View which shows a list of images, then it would be like this:
class ImagesController : Controller {
public ActionResult Index() {
List<ImageVM> images;
if( useAzure ) {
List<CloudStorageBlob> blobs = GetBlobs( ... );
images = blobs
// convert an Azure blob record into an ImageVM:
.Select( b => new ImageVM()
{
Url = b.BlobUrl
} )
.ToList();
}
else { // use local SQL
List<MyImageEntity> dbImages = GetImagesFromDB( ... );
images = dbImages
// convert a database MyImageEntity into an ImageVM:
.Select( i => new ImageVM()
{
Url = i.ImageAddress
} )
.ToList();
}
return this.View( images );
}
}
ViewModels:
public class ImageVM {
public String Url { get; set; }
public String TitleText { get; set; }
public String Etc { get; set; }
}
View:
#model List<ImageVM>
<ul>
#foreach(ImageVM image in this.Model) {
<li><img src="#image.Url" title="#image.TitleText" /></li>
}
</ul>
Fixed it in the end/provided workaround. So your answer helped a bit but not quite enough #Dai
To fix do this:
Model:
//SQL MODELs
//Filename: JoinUsersandJobsModel.cs
namespace client.Models
{
public class JoinUsersandJobsModel : DbContext
{
public tradesusers tradesusers { get; set; }
public jobs jobs { get; set; }
public uploadedfiles uploadedfiles { get; set; }
//Blob service does not need to be here
}
}
//FileModel - this is an additional model here to handle blob data
//Filename: FileListModel.cs
namespace client.Models
{
public class FileListModel
{
public FileListModel(IEnumerable<IListBlobItem> list)
{
if (list != null)
{
Files = new List<FileInfo>();
foreach (var item in list)
{
FileInfo info = FileInfo.CreateFromIListBlobItem(item);
if (info != null)
{
Files.Add(info);
}
}
}
}
public List<FileInfo> Files { get; set; }
}
public class FileInfo
{
public string FileName { get; set; }
public string URL { get; set; }
public long Size { get; set; }
public static FileInfo CreateFromIListBlobItem(IListBlobItem item)
{
if (item is CloudBlockBlob)
{
var blob = (CloudBlockBlob)item;
return new FileInfo { FileName = blob.Name,
URL = blob.Uri.ToString(),
Size = blob.Properties.Length };
}
return null;
}
}
}
//Controller for Azure SQL
private traderEntities db = new traderEntities();
BlobProfileImageServices _blobServices = new BlobProfileImageServices();
public ActionResult Index(string usernameCookie)
{
var viewModel = from u in db.tradesusers
join j in db.jobs on u.id equals j.jobbyuserid
where u.email.Equals(usernameCookie)
select new JoinUsersandJobsModel { tradesusers = u, jobs = j, uploadedfiles = pic };
return View(viewModel);
}
//Controller for Azure Blobs
//End by throwing back a Partial and return blobs of same Action type
//and of model blobs (Blobs)
//We later embed the partial into the client
public ActionResult loadMyBlob()
{
CloudBlobContainer blobContainer = _blobServices.GetCloudBlobContainer();
List<string> blobs = new List<string>();
foreach (var blobItem in blobContainer.ListBlobs())
{
blobs.Add(blobItem.Uri.ToString());
}
return PartialView("loadMyBlob", blobs);
}
//Design our Partial Strongly Typed and ref our Model for blobs
#model yourApp.Models.FileListModel
#{
ViewBag.Title = "File List";
}
<h2>File List</h2>
<ul>
#foreach (var item in Model.Files)
{
<li>
#item.FileName (#item.Size bytes)
</li>
}
</ul>
#Html.ActionLink("Upload Another File", "UploadFile")
//Finally embed our Partial into the View of the Action - "Index" in our case
//The embed code can be placed anywhere in your View
//Action will be executed on request and blob pulled through
<embed src='#Url.Action("loadMyBlob", "Profile")'>
If any one needs help on similar setup please let me know.
Refs:
ALSO props and thanks go out to John Ciliberti where I copied his idea from his book for the FileListModel Class and how to display it in View.
I am having difficulty passing an IEnumerable as a model. The data is populating a form on one page - and doing so correctly. Upon submission the model returns as null.
I've seen various posts on this and they mostly reference naming-conventions so I have attempted different methods of naming the parameters to try to avoid any confusion in the model binding.
I have also tried various models and helpers to try and pass the data and all have the same result.
Current implementation:
Models:
public class UserProfileListModel
{
public IEnumerable<UserProfileViewModel> UserProfileViewModels { get; set; }
}
public class UserProfileViewModel
{
public UserProfile UserProfile { get; set; }
public Role UserRole { get; set; }
public Team UserTeam { get; set; }
public Scope UserScope { get; set; }
}
View:
#model Project.WebUI.Models.UserPRofileListModel
SNIP
<fieldset>
<legend>Administrate Users:</legend>
<table class="adminTbl">
<thead>
<tr>
<th>UserName:</th>
<th>Role:</th>
<th>Team:</th>
<th>Scope:</th>
<th>Update:</th>
<th>Delete:</th>
</tr>
</thead>
<tbody>
#{foreach (var user in Model.UserProfileViewModels)
{
<tr>
<td>
<p>#user.UserProfile.UserName
#{if (!user.UserProfile.Membership.IsConfirmed)
{
using (Html.BeginForm("Confirm", "Account", FormMethod.Post, null)){
#Html.AntiForgeryToken()
#Html.Hidden("Token", user.UserProfile.Membership.ConfirmationToken)
#Html.Hidden("Name", user.UserProfile.UserName)
}
<input type="submit" value="Confirm" />}
}
</p>
</td>
#{using (Html.BeginForm("SaveUserChanges", "Account", FormMethod.Post, null))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(u => user.UserProfile)
if (user.UserProfile.UserName != User.Identity.Name && user.UserProfile.Membership.IsConfirmed)
{
<td>
#Html.DropDownListFor(u => user.UserRole, Project.WebUI.Controllers.AccountController.RoleList, new { #class = "formdrop" })
</td>
<td>
#Html.DropDownListFor(u => user.UserTeam, Project.WebUI.Controllers.AccountController.TeamList, new { #class = "formdrop" })
</td>
<td>
#Html.DropDownListFor(u => user.UserScope, Project.WebUI.Controllers.AccountController.ScopeList, new { #class = "formdrop" })
</td>
<td>
<input type="submit" value="Save Changes" onclick="return confirm('Are you sure you wish to update this user? ')" />
</td>
}
else
{
/*If user is self or not yet confirmed these are here to buffer the delete button into the last cell*/
<td></td>
<td></td>
<td></td>
<td></td>
}
}
}
<td>
#Html.ActionLink("Delete", "Delete", new { user.UserProfile.UserId }, new
{
onclick = "return confirm('Warning: Action cannot be undone. Are you sure you wish to permanently delete this entry?')"
})
</td>
</tr>
}
}
</tbody>
</table>
</fieldset>
Controller:
Populate View:
public ActionResult AdministrateUsers()
{
populateLists();
var query = repository.UserProfiles.OrderBy(e => e.UserName);
List<UserProfileViewModel> list = new List<UserProfileViewModel>();
foreach(UserProfile up in query)
{
UserProfileViewModel vm = new UserProfileViewModel() { UserProfile = up };
list.Add(vm);
}
UserProfileListModel models = new UserProfileListModel()
{
UserProfileViewModels = list.OrderBy(up => up.UserProfile.UserName)
};
return View(models);
}
Accept Post:
public ActionResult SaveUserChanges(UserProfileListModel model)
{
foreach (UserProfileViewModel upvm in model.UserProfileViewModels)
{
UserProfile up = new UserProfile()
{
UserId = upvm.UserProfile.UserId,
UserEmail = upvm.UserProfile.UserName,
UserName = upvm.UserProfile.UserName
};
if (ModelState.IsValid)
{
repository.SaveUserProfile(up);
}
else
{
return View(model);
}
}
return RedirectToAction("Index", "Admin");
}
The code does still need a lot of work but I can't get past getting the model back to the controller on post. I have also tried returning the UserProfileViewModel instead of the entire list.
Can anyone tell what I am doing wrong?
Thanks!
You have a lot of invalid html including form elements as child elements of tr elements and duplicate id attributes. If you want to post back UserProfileListModel then you need a single form element and use an EditorTemplate or a for loop (not foreach) to render the controls so they are correctly named with indexers.
You are also trying to bind your dropdown lists to complex objects (for example UserProfile, Role etc.). <select> elements (and all form controls) only post back key/value pairs so you need to bind to a value type (for example UserProfile.UserId).
Your SaveUserChanges() post method is also trying access properties of UserProfile but you don't even have controls for properties of UserProfile in the form that post back to this method (for example UserId = upvm.UserProfile.UserId, UserEmail = upvm.UserProfile.UserName, ...) so they will always be null.
You probalby need to bind properties in POST method like here:
public ActionResult Create([Bind(Include = "Id,Subject,Text,IsImportant")] Announcment announcment) {... }
So it will be:
public ActionResult SaveUserChanges([Bind(Include = "UserProfile,Role,UserTeam,UserScope")]UserProfileListModel model)
Have you specified your action method is for HTTP Post? And change your action method to accept UserProfileViewModels instead.
[HttpPost]
public ActionResult SaveUserChanges(UserProfileViewModels model)
{
You are also only posting back one model: UserProfileViewModels.
You have your form in your foreach loop, so each UserProfileViewModels has its own form. If you want to change it to post back your UserProfileListModel, move
#{using (Html.BeginForm("SaveUserChanges", "Account", FormMethod.Post, null))
outside of your foreach.
In my view this is what I have
#foreach (var match in Model.CommonMatches)
{
<tr>
<td>#match.StartDateTime</td>
<td>#match.EndDateTime</td>
<td>#match.AvailableAttendees.Count()</td>
<td>#Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new {commonMatch = #match })</td>
</tr>
}
Model.CommonMatches is of type List<Window>
public class Window
{
public DateTime StartDateTime { get; set; }
public DateTime EndDateTime { get; set; }
public IEnumerable<DataModels.Attendee> AvailableAttendees { get; set; }
}
This is how the value is being passed from controller
[HttpGet]
public ActionResult ViewStatus(Guid appointmentId)
{
var status = new ViewStatus
{
AttendeesWhoResponded = _appointmentRepository.GetAppointmentDetails(appointmentId).Attendees.Where(a=>a.HasResponded == true).ToList(),
NotAttending = _appointmentRepository.GetAppointmentDetails(appointmentId).Attendees.Where(a=>a.HasResponded == true && a.Responses == null).ToList(),
CommonMatches = _appointmentRepository.FindCommonMatches(appointmentId)
};
return View(status);
}
ViewStatus class
public class ViewStatus
{
public ViewStatus()
{
AttendeesWhoResponded = new List<DataModels.Attendee>();
NotAttending = new List<DataModels.Attendee>();
}
public List<DataModels.Attendee> AttendeesWhoResponded { get; set; }
public List<DataModels.Attendee> NotAttending { get; set; }
public IEnumerable<Window> CommonMatches { get; set; }
}
The action in controller that ActionLink of view is calling is:
[HttpGet]
public ActionResult AcceptAppointment(Window commonMatch)
{
return Content("ac");
}
When I inspect the value of commonMatch in controller's action. I'm getting the StartDateTime and EndDateTime but i'm not getting all the value of AvailableAttendees. It is currently shown as null.
AvailableAttendees that I'm expecting is of type IEnumerable<Attendee>. Is is not possible to pass the object the way I'm passing?
What should I do, to also get all the values of AvailableAttendees in controller along with dates?
Edit 1:
<table class ="table-hover table-striped">
<thead>
<tr>
<td>Start time</td>
<td>End time</td>
<td>Number of Attendees</td>
</tr>
</thead>
#for (var count = 0; count < Model.CommonMatches.Count();count++ )
{
using (Html.BeginForm("AcceptAppointment", "Appointment", FormMethod.Post))
{
<tr>
<td>#Model.CommonMatches[count].StartDateTime</td>
<td>#Model.CommonMatches[count].EndDateTime</td>
<td>#Model.CommonMatches[count].AvailableAttendees.Count()</td>
#*<td>#Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new { commonMatch = #match })</td>*#
#for(var j=0;j<Model.CommonMatches[count].AvailableAttendees.Count();j++)
{
<td>#Model.CommonMatches[count].AvailableAttendees[j].FirstName</td>//to check if the value is null or not, just a test
<td>#Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].FirstName)</td>
<td>#Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].LastName)</td>
<td>#Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].Email)</td>
<td>#Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].AttendeeId)</td>
}
<td><input type="submit" value="Accept"/></td>
</tr>
}
}
</table>
You need to post your model back, this would involve changing your controller method to this:
Controller
[HttpPost]
public ActionResult AcceptAppointment(List<Window> model)
{
return Content("ac");
}
View
You view would need a form and a submit button rather than an ActionLink. I have take the table formatting out to simplify the below.
Indexing your collections with a for loop so the model binder knows how to handle them, this is actually two loops as it is a collection within a collection. The hidden values have to be rendered too in order to be posted back (please forgive any typos).
#for(var i = 0; i < Model.CommonMatches.Count; i ++)
{
<div>
#using (Html.BeginForm("AcceptAppointment", "Appointment", FormMethod.Post)
{
#Html.HiddenFor(m => Model.CommonMatches[i].StartDateTime)
#Html.HiddenFor(m => Model.CommonMatches[i].EndDateTime)
#Model.CommonMatches[i].StartDateTime <br/>
#Model.CommonMatches[i].EndDateTime <br/>
#for(var j = 0; Model.CommonMatches[i].AvailableAttendees.Count; j++)
{
#Html.HiddenFor(m => Model.CommonMatches[i].AvailableAttendees[j].Prop1)<br/>
#Html.HiddenFor(m => Model.CommonMatches[i].AvailableAttendees[j].Prop2)<br/>
}
<input type="submit" value="Accept" />
</div>
}
}
There are plenty of things you need to taken care
<td>#Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new {commonMatch = #match })</td>
Calls
[HttpGet]
public ActionResult AcceptAppointment(Window commonMatch)
{
return Content("ac");
}
Here you are navigating using a link <a href>. Basically you are issuing a get request. In get request, you can pass the data to server only via Query String. But your case, preparing a query string dynamically before navigating to url is bit more complex. But you can do it with a JavaScript like onclick=prepareHref(this);
#Html.ActionLink("Accept", "AcceptAppointment", "Appointment",
new {commonMatch = #match }, new {onclick=prepareHref(this)})
Then in Javascript
function prepareHref(obj)
{
var qsData="?StartDateTime='2014-02-25'&EndDateTime='2014-02-25'&AvailableAttendees[0].prop1=value1, etc"; // data should be obtained from other td elements
obj.href=obj.href+qsData;
}
But this is not a suggested way of doing it.
In case, if you want to open other page and show the url, better pass the id and load data again.
Option 1:
The better way could be submit the detail in the hidden field as explained by #hutchonoid.
Option 2:
or submit the details in jQuery ajax $.post method. Either way you need to use POST
#Html.ActionLink("Accept", "AcceptAppointment", "Appointment",
new {commonMatch = #match }, new {onclick=postMyData()})
function postMyData(){
var postData={};
postData.StartDateTime='';
postData.EndDateTime='';
postData.AvailableAttendees=[];
//for each AvailableAttendees prepare object
postData.AvailableAttendees[0]= {};
postData.AvailableAttendees[0].prop1=value1;
$.post('/Appointment/AcceptAppointment/',{data:postData},function(data){
});
return false;
}
[HttpPost]
public ActionResult AcceptAppointment(Window commonMatch)
{
return Content("ac");
}
I like to do one simple control for day transactions.
That need to show me how much transaction we have this day (close or open trans) and when the manager click the number of transaction I would like to send all this list of transactions into a nice table.
But I can't find the way to do it. Not even across the web.
here is my try but nothing.
I am open for suggestion =)
Here is my ViewModel
public class SIMcontrolsViewModel
{
public DTControls DTransactionControl { get; set; }
}
public class DTControls
{
public DateTime TDate { get; set; }
public int NumOfTransaction { get; set; }
public List<SIMsale> SIMsaleList { get; set; }
public DTControls()
{
SIMsaleList = new List<SIMsale>();
}
}
the Controller look like I fill all the data and I sent it to view
[AdminAuthorization]
public ActionResult DateTransactionsControl(DateTime? date)
{
SIMcontrolsViewModel vm = new SIMcontrolsViewModel();
vm.DTransactionControl = new DTControls();
if (!date.HasValue)
date = DateTime.Now;//.Today;
vm.DTransactionControl.TDate = date.Value;
try
{
using (CompanyContext db = new CompanyContext())
{
var saleLst = db.SIMsales.ToList();
foreach (var sale in saleLst)
{
if (..)
vm.DTransactionControl.SIMsaleList.Add(sale);
}
var tCount = vm.DTransactionControl.SIMsaleList.Count;
vm.DTransactionControl.NumOfTransaction = tCount;
}
}
catch (Exception ex)
{..}
return View(vm);
}
Now on my View I try to send this list from this #Html.ActionLink like we can see here.
#model oCc.IPToGo.ViewModel.SIMcontrolsViewModel
<fieldset>
<table border="0" class="display">
<thead>
<tr>
<th style="width:100px">Date</th>
<th style="width:100px">#Html.DisplayNameFor(model => model.DTransactionControl.NumOfTransaction)</th>
</tr>
</thead>
<tbody>
<tr style="text-align: center">
<td>#Model.DTransactionControl.TDate.ToShortDateString()</td>
#if (Model.DTransactionControl.NumOfTransaction != 0)
{
<td>
#Html.ActionLink(Model.DTransactionControl.NumOfTransaction.ToString(), "../SIMsale/",
new { sell = Model.DTransactionControl.SIMsaleList },
new { style = "font-weight: bold; color: Highlight" })
</td>
}
else
{
<td style="color:red">0</td>
}
</tr>
</tbody>
</table>
</fieldset>
The problem is that the view/controller who supposed to get this list is getting an empty list.
10Q =)
You can simply sent the SIMsales condition like sellerId on your ViewModel and a Hidden field on Razor to keep the data and on pthe post function (on your controller) just retrive all of those SIMsales that you count on the Get func.
(I know that was two year before but maybee that can help)
I would associate an id with the transaction count and pass that back to the controller through an ajax call
$.ajax({
url: "#(Url.Action("Action", "Controller"))",
type: "POST",
cache: false,
async: true,
data: { id: 'associatedID' },
success: function (result) {
$(".Content").html(result);
}
});
create a partial view for displaying the table and on your controller populate and return the partial view using the passed id
public PartialViewResult BuildTable(int id){
Model model = (get results from database for id)
return PartialView("_Partial", model);
}
then put a div on your view with a class of Content (or whatever you want to call it). Hopefully this helps.