Get ID from an input defined in the model - asp.net-mvc-3

Not sure how clear the title is.
I have file uploading script. An input field is created dynamically with javascript with the name of testdata. One input field is created for every file that the user decides to upload. My model so far just gets the value of the field.
public string testdata { get; set; }
Later in my controller I'm getting the value and writing it to a file.
Problem is when uploading multiple files, the controller collects the values from all inputs and write them all together on every line. What I want is to have a seperate line with the value from each input (each upload). The controller does simply what I asked it to do. I don't know how to access the id of the input field. I know I need to change my model but not sure how. Any help would be apreciated. Thanks!
The controller, in case it wasn't very clear:
[HttpPost]
public ActionResult Index(UploadsModel model, IEnumerable<HttpPostedFileBase> files)
{
string uploadDir = Server.MapPath("~/App_Data/uploads");
foreach (string fileKey in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileKey];
StreamWriter tw = System.IO.File.AppendText(Path.Combine(uploadDir, "post_data.txt"));
tw.WriteLine(System.DateTime.Now + " " + file.FileName + " " + model.testdata);
tw.Close();
file.SaveAs(Path.Combine(uploadDir, file.FileName));
}
//could go somewhere else...
return RedirectToAction("Index");
}
EDIT:
Found a workaround. Will create dynamically a hidden field for each regular field. Will pass the value of the first one to it, will create new property in my model and when uploading and saving, I will compare the file name and the hidden field value.

Related

How to check if the first row or columns of Excel file is valid in Laravel Excel?

I'm trying to check if the excel file a user has uploaded has the correct columns/first row/attributes before reading into its other rows. I'm using Laravel 4 with MaatWebsite's Laravel Excel.
I have created a function which allows users to update the employee table of the system's database by importing an excel file.
Now the correct excel file, has, let's say, 3 columns: firstname, lastname, and username. If the excel file has all these attributes/columns, I will now read each of the following rows and validate each row, which isn't really a part of my problem as of now.
But if any of the 3 attribute/column is not present in the excel file, I'd ignore the request and return an error.
I tried using this, which gets lastname attribute:
$sample = Excel::selectSheetsByIndex(0)->load($readFile, function($reader){})->get(array("lastname"));
But even though lastname hasn't been found, $sample is still not null so I won't be able to check if lastname is present or not.
How can I check if the attributes/columns are present/not?
UPDATE:
The answer that I selected would work perfectly if the first row after the attributes row has all the needed attributes. For example: If it has values for firstname, lastname, and username.
But if in cases where first name value (or any attritbute value for that matter) of the first non-attribute row (attribute row referring to the column names) is missing, then the provided script would return false, even if the excel file has all the firstname, lastname, and username attributes.
So I modified the script to this:
First, I read the excel file. I also declared a Boolean variable to mark if the excel file is valid or not.
$excelChecker = Excel::selectSheetsByIndex(0)->load('path/to/file', function($reader){})->get()->toArray();
$excelIsValid = false;
Then I loop through all the results and check if at least once, all the values required (firstname, lastname, and username) have been set or are present.
foreach($excelChecker as $ex){
if(isset($ex["lastname"]) && isset($ex["firstname"]) && isset($ex["username"])){
$excelIsValid = true;
}
}
Explanation:
If $excelIsValid is still false at the end of the loop, then not once did the file had all the attributes required. This either means the file is empty, has the wrong attribute names, or does not have any valid row. In short, the file is invalid and should not be in the system.
I prepared this sample script:
Route::get('/', function() {
$isError = false;
Excel::load('file.xls', function($reader) use (&$isError) {
$firstrow = $reader->first()->toArray();
if (isset($firstrow['firstname']) && isset($firstrow['lastname']) && isset($firstrow['username'])) {
$rows = $reader->all();
foreach ($rows as $row) {
echo $row->firstname.' '.$row->lastname.' '.$row->username."<br />";
}
}
else {
$isError = true;
}
});
if ($isError) {
return View::make('error');
}
});
The script loads file and check if there are columns you want. It doesn't check if there are more columns - of course if you want you can add exta check - count($firstow) == 3. If there is error it sets $isError to true and in route it displays a template.
In Laravel Excel 3.1 you can use
public function import()
{
$column= (new HeadingRowImport)->toArray('users.xlsx');
if (isset($column['firstname']) && isset($column['lastname']) && isset($column['username'])) {
//dd('columns found');
//your code
}else{
//dd('columns not found');
//if not found show error or something
}
}
You can do anything inside of that if else or you can use your logic

how to pass in a reference variable into a RenderPartial?

I am trying to pass a modelclass store to a RenderPartial. The goal for the renderpartial is to change/set values on this (store)model. I have been trying like this:
#{ Html.RenderPartial("test", new store(){Output=""}); }
#{ Html.RenderPartial("test", new store(){Output2=""}); }
public class store
{
public string Output { get; set; }
public string Output2 { get; set; }
}
the Partial 'test' has to change the Output properties. Is it uberhaupt possible and if yes how to do this? The renderpartial contains a javascript to calculate the value of the properties.
RenderPartial is meant to get either none of the data from the parent or a part of the model.
The overloads at:
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.renderpartialextensions.renderpartial(v=vs.108).aspx
Tell you object isn't a custom object but meant to be part of the Model, ex Model.Customers
Pass the required value from your model to the partial and let the partial create it's own objects.
If you really want to pass it to the partial then create a new view model for your parent view and set the Output property in your viewmodel and pass it to the partial.
Note also that the partial gets it's own copy of the data and cannot update the parents copy so that may defeat what you actually want here.
If you need some other calculate data do it in your controller prior to passing it to the view if possible.
#store st = new store(){Output="", Output2=""};
#{ Html.RenderPartial("test", new RouteValueDictionary {{"output", st.Output}, {"output2", st.Output2}}); }

Is there any way to pass a whole model via html.actionlink in ASP.NET MVC 3?

How do I pass a whole model via html.actionlink or using any other method except form submission? Is there any way or tips for it?
Though it's not advisable in complex cases, you can still do that!
public class QueryViewModel
{
public string Search { get; set; }
public string Category { get; set; }
public int Page { get; set; }
}
// just for testing
#{
var queryViewModel = new QueryViewModel
{
Search = "routing",
Category = "mvc",
Page = 23
};
}
#Html.ActionLink("Looking for something", "SearchAction", "SearchController"
queryViewModel, null);
This will generate an action link with href like this,
/SearchController/SearchAction?Search=routing&Category=mvc&Page=23
Here will be your action,
public ViewResult SearchAction(QueryViewModel query)
{
...
}
No, you cannot pass entire complex objects with links or forms. You have a couple of possible approaches that you could take:
Include each individual property of the object as query string parameters (or input fields if you are using a form) so that the default model binder is able to reconstruct the object back in the controller action
Pass only an id as query string parameter (or input field if you are using a form) and have the controller action use this id to retrieve the actual object from some data store
Use session
You could use javascript to detect a click on the link, serialize the form (or whatever data you want to pass) and append it to your request parameters. This should achieve what you're looking to achieve...

how to take input field prefix name in MVC3 Razor

I have ViewModel, View which uses this viewmodel and controller
in view I have input fields like this:
#Html.EditorFor(model => model.TransitApplication.ApplicationDate)
and field name is TransitApplication_ApplicationDate
I want to update some data from view in database but there is one problem
controller update source
public ActionResult Update(int id, FormCollection collection)
{
string prefix = "TransitApplication";
TransitApplication transitApplication = transitApplicationRepozitory.GetById(id);
if (transitApplication == null)
return Content("Error! Not Found!");
if (TryUpdateModel(transitApplication, prefix))
{
if (ModelState.IsValid)
{
transitApplicationRepozitory.Update(transitApplication);
transitApplicationRepozitory.Save();
return RedirectToAction("Index");
}
}
return Content("Error!");
}
I want to take prefix (TransitApplication) name programmatically and not like I have
string prefix = "TransitApplication";
some advice?
Seeing that the form prefix is built using the Class Name of the Model property, what about:
if (TryUpdateModel(transitApplication, typeof(TransitApplication).Name))
This removes your magic string - although this isn't actually the property name on the model class, but I'm guessing that if you renamed class, you'd probably want to rename the referenced property on the model too - although it is a little brittle.
The alternative is you could use something like this GetPropertyInfo method which would allow you to get the property name as a string like this var propertyInfo = GetPropertyInfo(yourModelObject, u => u.UserID); - although you don't currently have an instantiated model class in your action atm.

MVC ddl value after postback

I have a ddl which is populated with hours of day 01-23. This is on a form which is used to book an item of equipment. The hour is populated to a db field. The issue is this, when the booking form is opened to alter the time the ddl shows the hour that was booked, when changed though and the form is submitted the value passed on post is the initial value from db not the new selected hour.
this is the basic pieces of code. any idea why the newly selected ddl value is not passed to the model??
View
<%= Html.DropDownList("ddl_Hour", Model.ddlHour,
new { #class = "DropDown", style = "width: 40px” })%>
Model
private string _ddlHourSelectedValue = "0";
public SelectList ddlHour
{
get
{
return (new System.Web.Mvc.SelectList(_ddlHour, "intValue", "Text", Convert.ToInt32(_ddlHourSelectedValue)));
}
}
public string ddlHourSelectedValue
{
get
{
return _ddlHourSelectedValue;
}
set
{
_ddlHourSelectedValue = value;
}
}
param[6] = new SqlParameter("#Timeslot", ddlHourSelectedValue);
The field in your view is called "ddl_Hour" However is there a variable in your Model with the same name? Otherwise the MVC framework will not automatically populate the value in the model.
Two ways you could go about this.
1
In your controller methods that accepts a post, you can add the parameter: FormCollection fc to the method. This key value pair collection will allow you to fetch results from fields in the post data like so:
string selectedValue = fc["ddl_Hour"];
2
Or you can modify your model to include a variable with the same name as the drop down list so that it is automatically populated for you.
public string ddl_Hour { get; set; }
You should then be able to access the result of the drop down list selection on post from that variable.

Resources