I have added an extra "title" field in my POST form and created a "title" attribute in my model. After the video has been uploaded the server is directed to another controller. This is done by setting the redirect field in the policy file. Now how can I access the title field in the redirected controller?
The POST form :
<form action="#Model.FileUploadModel.FormAction" method="#Model.FileUploadModel.FormMethod" enctype="#Model.FileUploadModel.FormEnclosureType" >
<input type="hidden" name="key" value="#Model.FileUploadModel.FileId" />
<input type="hidden" name="AWSAccessKeyId" value="#Model.FileUploadModel.AWSAccessKey" />
<input type="hidden" name="acl" value="#Model.FileUploadModel.Acl" />
<input type="hidden" name="policy" value="#Model.FileUploadModel.Base64EncodedPolicy" />
<input type="hidden" name="signature" value="#Model.FileUploadModel.Signature" />
<input type="hidden" name="redirect" value="#Model.FileUploadModel.RedirectUrl" />
<div class="row">
**<label for="Title" style="padding-right: 5px;">Title (optional) </label>
<input type="text" name="Title" style="width: 200px;" />**
</div>
<div class="row_clear"></div>
<div class="row">
<input type="file" name="file" size="100" id="file"/>
</div>
</form>
and my FileUploadModel
public FileUploadModel(string publicKey, string privateKey, string bucketName, string redirectUrl)
{
myPrivateKey = privateKey;
FormAction = string.Format("https://{0}.s3.amazonaws.com/", bucketName);
FormMethod = "post";
FormEnclosureType = "multipart/form-data";
Bucket = bucketName;
FileId = "u5/i/" + Guid.NewGuid().ToString();
AWSAccessKey = publicKey;
Acl = "private";
RedirectUrl = redirectUrl;
}
public string FormAction { get; private set; }
public string FormMethod { get; private set; }
public string FormEnclosureType { get; private set; }
public string Bucket { get; private set; }
public string Acl { get; private set; }
public string Policy { get; private set; }
public string FileId { get; private set; }
public string AWSAccessKey { get; private set; }
public string RedirectUrl { get; private set; }
[Display(Name = "Title (optional)")]
public string Title { get; set; }
[Display(Name = "File")]
public HttpPostedFileBase File { get; set; }
public int? Page { get; set; }
public string SearchString { get; set; }
}
}
Here is the link I referred for creating policy form.
Link
I worked around the problem by sending the title attribute through the URL.
In my RouteConfig file I added a new route:
routes.MapRoute(
name: "Transcode",
url: "{controller}/{action}/{title}/{id}",
defaults: new
{
controller = "Videos",
action = "Transcode",
id = UrlParameter.Optional
}
);
and then in the Transcode action I added a title parameter. Then finally the value I passed to the redirect URL attribute was: " http://dev.area.local/Videos/Transcode/title"
Related
I have a view model set up as:
public class BookViewModel
{
public int Id { get; set; }
[Display(Name = "Book Name")]
public string Name { get; set; }
public string Path { get; set; }
[Display(Name = "Pdf Book")]
public IFormFile BookPdfFile { get; set; }
}
In the view, I am using the view model properties
<form asp-action="CreateEdit" method="post" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input asp-for="Id" type="hidden" />
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
#if (!string.IsNullOrEmpty(Model.BookPath))
{
<div class="form-group">
<label>Uploaded Book:</label>
<a asp-action="Download" asp-route-id="#Model.Id">#Model.Name</a>
</div>
}
<div class="form-group">
<label asp-for="BookPdfFile" class="control-label"></label>
<input class="form-control" type="file" asp-for="BookPdfFile" accept=".pdf">
<span asp-validation-for="BookPdfFile" class="text-danger"></span>
</div>
</form>
Using this View model in the view in this way always asks for the file to be uploaded. If the file is uploaded during the create mode or if it has the file path, how to not ask to make the form file required?
The Book entity is:
public class Book
{
public int Id { get; set; }
[MaxLength(100)]
public string Title { get; set; }
[MaxLength(50)]
public string? Path { get; set; }
public ICollection<BookChapter> Chapters { get; set; }
}
How could I modify my code to make the form file not required if the path already exists in the DB?
On the server side I could add the validation attribute but how would I make that work on the client side as well?
I have yet not worked on posting and saving the files to the controller on HttpPost. So, my controller is just a one-line initializing the view model.
public async Task<IActionResult> CreateBook()
{
BookViewModel bookVM = new BookViewModel();
return View("CreateEdit", bookVM);
}
I'm trying to pass the user's email to Identity's ResendEmailConfirmation.cshtml class from the register page, so that it is displayed on view in the Email Input box.
Register Page - The link to redirect the user to the Resend Email Confirmation page
<a asp-area="Identity" asp-page="/Account/resendemailconfirmation" asp-route-email="#Model.Input.Email" class="resend-confirm-email-submit">Resend confirmation email</a>
ResendEmailConfirmation.cshtml - Relevant Parts
public ResendEmailConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender emailSender)
{
_userManager = userManager;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
}
public void OnGet(string email)
{
// My attempt
InputModel inputModel = new InputModel();
inputModel.Email = email;
}
ResendEmailConfirmation View - Email Input Box
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email" class="register-heading-style"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
#*<button type="submit" class="btn btn-primary">Resend</button>*#
<button type="submit" class="register-submit"><span>Resend</span></button>
</form>
Thank you
You should use this way to define Input in OnGet():
Register.cshtml.cs to get the email (You didn't show this part of code, so I directly define the value):
public void OnGet()
{
Input =new InputModel()
{
Email = "asd#asd.com"
};
}
Then ResendEmailConfirmation.cshtml.cs to show the email that passed from register page:
public void OnGet(string email)
{
Input = new InputModel() //you get value from Input.Eamil in view, so you should define Input, not inputmodel
{
Email = email
};
}
You do not have to change the razor view pages.
Result:
I have following html form
<input type="hidden" name="JsonCustomers" data-bind="value: ko.toJSON(customers)" />
<input type="hidden" name="JsonMaterials" data-bind="value: ko.toJSON(materials)" />
<button type="submit" class="btn btn-sm btn-primary">Submit</button>
and input model class
public class SubmitViewModel
{
public string JsonCustomers { get; set; }
public string JsonMaterials { get; set; }
}
Controller action
[HttpPost]
public IActionResult Submit(SubmitViewModel model)
{
throw new NotImplementedException();
}
it is possible to automap Json into something like this ?
public class SubmitViewModel
{
public IEnumerable<InputCustomer> Customers { get; set; }
public IEnumerable<InputMaterial> Materials { get; set; }
}
I would like to skip conversion step from the Json into collection and ideally use data annotations with ModelState.IsValid function. Any idea ?
UPDATE
html
<input type="hidden" name="JsonCustomers" data-bind="value: ko.toJSON(customers)" />
<input type="hidden" name="JsonMaterials" data-bind="value: ko.toJSON(materials)" />
<input type="hidden" name="Customers" data-bind="value: ko.toJSON(customers)" />
<input type="hidden" name="Materials" data-bind="value: ko.toJSON(materials)" />
content of JsonCustomers after form submit
[{"isChecked":true,"name":"CompanyA","volume":"80","expectedDateOfOrder":"1.1.2018"},{"isChecked":true,"name":"CompanyB","volume":"100","expectedDateOfOrder":"2.2.2018"},{"isChecked":true,"name":"CompanyC","volume":"150","expectedDateOfOrder":"3.3.2018"}]
customer class
public class Customer
{
public bool? IsChecked { get; set; }
public string Name { get; set; }
public string Volume { get; set; }
public string ExpectedDateOfOrder { get; set; }
}
the issue is that public IEnumerable<Customer> Customers collection has Count = 0, i dont know why.
this is from FormCollection
With help from #Alex Riabov and based on this discussion https://github.com/aspnet/Mvc/issues/5760
model.Customers = JsonConvert.DeserializeObject<IEnumerable<InputCustomer>>(model.JsonCustomers);
in the controller action did the trick.
I try to bind an object like this in a Action
public class MonthDataViewModel
{
public int Year { get; set; }
public int Month { get; set; }
public IEnumerable<MoneyDataItemViewModel> MoneyCosts { get; set; }
}
public class MoneyDataItemViewModel
{
public string Title { get; set; }
public decimal Cost { get; set; }
}
Is that possible? How do i design the form?
I try a few times but the property MoneyCosts won't be bind , and this is the data i submited:
Year=2016
Moneh=8
MoneyCosts.Title=ABC
MoneyCosts.Cost=100
MoneyCosts.Title=DEF
MoneyCosts.Cost=200
I saw a modelbinder called ArrayModelBinder<T> , how do i use it?
If you use x-www-url-formencoded content type then try to change(if possible) your post data like below:
Year=2016&Month=8&MoneyCosts[0].Title=ABC&MoneyCosts[0].Cost=100&MoneyCosts[1].Title=DEF&MoneyCosts[1].Cost=200
How do i design the form?
<form asp-controller="Home" asp-action="AccountName" method="post">
<input type="text" name="Year" />
<input type="text" name="Month" />
#for(var i = 0; i < count; i++)
{
<input type="text" name="#("MoneyCosts["+ i + "].Title")" />
<input type="text" name="#("MoneyCosts["+ i + "].Cost")" />
}
<input type="submit" value="Submit" />
</form>
If you use json content type, your data should be something like this:
{"Year": "2016", "Month":"8", "MoneyCosts":[{"Title":,"ABC"}, ...]}
in the case of json request you should use FromBody in action method.
[HttpPost]
public IActionResult ActionName([FromBody]MonthDataViewModel model)
There has been a lot of questions about this... but somehow I can't get this binding to work and I'm still getting null values in my posted View Model. This is MVC 4.
Here is the Main View Model
public class RoleVM {
[Required]
[Display(Name = "Name of the Role")]
public string Role {get; set;}
public IEnumerable<RolePermission> permissions { get; set; }
}
Here is the RolePermission Class
public class RolePermission {
public int id;
public bool permission_value;
public string name { get; set; }
}
Here is GET Create Method in the controller
public ActionResult Create() {
RoleVM role_vm = new RoleVM();
var allpermissions = from p
in permission_repo.GetPermissions()
select p;
role_vm.permissions = from p
in allpermissions
select new RolePermission
{ name = p.name, id = p.PermissionId, permission_value = false };
return View(role_vm);
}
Here is the Create.cshtml file
#model RoleVM
#using (Html.BeginForm("Create", "Role",
FormMethod.Post, new { #class = "permission_form" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>RoleVM</legend>
<div class="form-item">
#Html.LabelFor(model => model.Role)
#Html.EditorFor(model => model.Role)
#Html.ValidationMessageFor(model => model.Role)
</div>
#Html.EditorFor(model => model.permissions)
<p>
<input class="submit-btn" type="submit" value="Create" />
</p>
</fieldset>
}
Next here is the rolepermissions.cshtml file located in ~/Views/Shared/EditorTemplates
#model RolePermission
<div class="form-item">
#Html.HiddenFor(modelItem => modelItem.id)
#Html.LabelFor(modelItem => modelItem.permission_value, Model.name)
#Html.CheckBoxFor(modelItem => modelItem.permission_value)
</div>
Here is an example of one of the html items that is rendered on page
<div class="form-item">
<input data-val="true" data-val-number="The field Int32 must be a number." data-val-required="The Int32 field is required." id="permissions_2__id" name="permissions[2].id" type="hidden" value="3" />
<label for="permissions_2__permission_value">Role-Edit</label>
<input data-val="true" data-val-required="The Boolean field is required." id="permissions_2__permission_value" name="permissions[2].permission_value"
type="checkbox" value="true" /><input name="permissions[2].permission_value" type="hidden" value="false" />
</div>
Finally here is the Create POST method
[HttpPost]
public ActionResult Create(RoleVM rolevm)
{
//In here rolevm.role is populated based on the textbox input
//However rolevm.permissions is there with the correct
//number of items, but the values all are not binded
// id is null, name is empty, and permission_value is false
// regardless of which checkboxes were checked
return RedirectToAction("Index");
}
Any help on the binding issue with the posted model would be really great.
This was a simple issue, if someone else comes across it maybe this will help them. I didn't have the properties on the class declared as properties with get; set;
public class RolePermission {
public int id { get; set; }
public bool permission_value { get; set; }
public string name { get; set; }
}