I have a page Item Edit with multiple partial rendered forms for images delete. Item Edit page:
#model EditModel
<form method="post" enctype="multipart/form-data">
<input asp-for="ItemModel.Id" type="hidden" />
<input asp-for="ItemModel.AllOtherFields" type="hidden" />
</form>
#if (Model.ItemModel.ImageViewModels != null && Model.ItemModel.ImageViewModels.Any())
{
foreach(var imageViewModel in Model.ItemModel.ImageViewModels)
{
Html.RenderPartial("ItemImage/_itemImageEdit", imageViewModel);
}
}
ItemImage/_itemImageEdit
#model ViewModels.ItemImageViewModel
<form asp-controller="Images" asp-action="Delete" method="post">
<input type="hidden" asp-for="#Model.Id" />
<img src="#Url.Action("Get", "Images", new { id = Model.Id })" />
<input type="submit" value="Delete" />
</form>
and here is my strange final html
<form method="post" action="/Images/Delete/5" novalidate="novalidate">
<input type="hidden" data-val="true" data-val-required="The Id field is required." id="Id" name="Id" value="5">
<img src="/Images/Get/10">
<input type="submit" value="Delete">
</form>
Where 5- Item id and 10 - image Id. So this is expected and correct
<img src="/Images/Get/10">
while this is not. Item Id used instead of id (ItemImageViewModel.id)
action="/Images/Delete/5"
I have no idea why does #Model.Idgenerate different ids on the same subview.
Edit1:
public class ItemImageViewModel
{
[BindProperty]
public int Id { get; set; }
public string Title { get; set; }
public int ItemId { get; set; }
}
public class ItemViewModel
{
public ItemViewModel()
{
}
public ItemViewModel(ItemViewModel vm)
{
Id = vm.Id;
Title = vm.Title;
ImageViewModels = vm.ImageViewModels;
}
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<ItemImageViewModel> ImageViewModels { get; set; }
}
I have removed unrelated fields.
Debugger shows alright
Now this weird piece of code generates what it supposed to generate
<form action="#Url.Action("Delete", "Images", new { id = Model.Id })" method="post">
<input type="hidden" id="Id" name="Id" value="#Html.DisplayFor(m => Model.Id)" />
#Html.HiddenFor(m => Model.ItemId)"
<img src="#Url.Action("Get", "Images", new { id = Model.Id })" />
<input type="text" asp-for="#Model.Title" />
<input type="submit" value="Delete" />
</form>
<form action="/Images/Delete/10" method="post" novalidate="novalidate">
<input type="hidden" id="Id" name="Id" value="10">
<input data-val="true" data-val-required="The ItemId field is required." id="ItemId" name="ItemId" type="hidden" value="5">"
<img src="/Images/Get/10">
<input type="text" id="Title" name="Title" value="Jacket">
<input type="submit" value="Delete">
</form>
Related
I have a class that includes one dictionary<int,string>.
int is the key of radio button and value is the choice title.
I'm trying to get a list of dictionaries in controller includes keys and values of radio buttons.
when I run the program the list is 0. I think there is something wrong with the name of the radio buttons and input for choice title but I don't know what should I write.
public class ChoiceQuestion
{
public int QuestionId { get; set; }
public Dictionary<int, string> Choice { get; set; }
public int Answer { get; set; }
}
in the controller I have this:
public IActionResult CreateQuestion(int courseId, List<ChoiceQuestion> choices,
QuestionType type, Question question)
{
_questionService.AddQuestion(courseId, type, choices, question);
return RedirectToAction("Index");
}
and this is my view:
<div class="form-group choiceDiv" style="display: none;" id="choiceDiv">
<a id="plus"><i class="glyphicon glyphicon-plus"></i></a>
<input type="radio" name="choices.choice[0].key" value="1" />
<input type="text" placeholder="گزینه " name="choices.choice[0].value" />
<input type="radio" name="choices.choice[1].key" value="1" />
<input type="text" placeholder="گزینه " name="choices.choice[1].value" />
<span asp-validation-for="Choice" class="text-danger"></span>
</div>
Firstly you want to pass data to List<ChoiceQuestion> choices,so your name of input need to be choices[xxx].choice[xxx].
And then,you can change your text type inputs name before form submitting,so that text type inputs' value will be binded to dictionary of List<ChoiceQuestion> choices.
Here is a working demo:
<form method="post" id="myform">
<div class="form-group choiceDiv" style="display: none;" id="choiceDiv">
<a id="plus"><i class="glyphicon glyphicon-plus"></i></a>
<input type="radio" name="choices[0].choice[0].key" value="1" />
<input type="text" placeholder="گزینه " name="choices[0].choice[key]" value="choicetitle1" />
<input type="radio" name="choices[0].choice[1].key" value="2" />
<input type="text" placeholder="گزینه " name="choices[0].choice[key]" value="choicetitle2" />
<span asp-validation-for="Choice" class="text-danger"></span>
</div>
<input type="submit" value="submit" />
</form>
<script>
$('#myform').submit(function () {
var keys = [];
var count = 0;
$("#choiceDiv input[type='radio']").each(function () {
keys.push($(this).val());
});
$("#choiceDiv input[type='text']").each(function () {
$(this).attr("name", $(this).attr("name").replace("key", keys[count]));
count++;
});
});
</script>
I change text type input names to choices[0].choice[key],and before form submitting,I replace 'key' in name to the value of radio button.And then form will post dictionary data.
result:
Or you can remove radio buttons,and use view like the following:
<div class="form-group choiceDiv" style="display: none;" id="choiceDiv">
<a id="plus"><i class="glyphicon glyphicon-plus"></i></a>
<input type="text" placeholder="گزینه " name="choices[0].choice[1]" value="choicetitle1"/>
<input type="text" placeholder="گزینه " name="choices[0].choice[2]" value="choicetitle2"/>
<span asp-validation-for="Choice" class="text-danger"></span>
</div>
And then you will get key=1,value="choicetitle1";key=2,value="choicetitle2" in dictionary.
I use ASP NET with VueJS. ASP NET render view component:
<script type="text/x-template" id="form-template">
#if (string.IsNullOrEmpty(Model.LastName))
{
<input asp-for="LastName" class="form-control" maxlength="100" autofocus required />
}
else
{
<input asp-for="LastName" class="form-control" maxlength="100" required />
}
</script>
My action on C#:
public async Task<ActionResult<ViewComponent>> GetAdditionalFormRegistrationComponentAsync()
{
var customerViewModel = new CustomerAdditionFormViewModel
{
LastName = "русские символы"
};
return ViewComponent("FormRegistration", customerViewModel);
}
}
ViewComponent:
public Task<IViewComponentResult> InvokeAsync(CustomerAdditionFormViewModel customerViewModel)
{
return Task.Run<IViewComponentResult>(() => View(customerViewModel));
}
LastName write in English input value OK. But if LastName fill in russian I get:
How fix this?
I have found solution.
Need add Html.Raw()
<input value=“#Html.Raw(Model.LastName)" class="form-control" maxlength="100" autofocus required />
or
services.AddWebEncoders(options =>
{
options.TextEncoderSettings = new TextEncoderSettings();
options.TextEncoderSettings.AllowRange(UnicodeRanges.All);
});
I have a program with login and logout.
I have an exercise class, I have a create view that allows me to create exercises that are composed by name, photo, video.
I fill the form in View Create and when I click create this error appears to me
NullReferenceException: Object reference not set to an instance of an object.
WebApplication1.Controllers.ExerciciosGinasiosController.Create(ExerciciosGinasio exerciciosGinasio, IFormFile fotografia, IFormFile video) in ExerciciosGinasiosController.cs
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
In the exercise class I have
[Table("Exercicios_Ginasio")]
public partial class ExerciciosGinasio
{
public ExerciciosGinasio()
{
Inclui = new HashSet<Inclui>();
}
[Key]
[Column("IDExercicios_Ginasio")]
public int IdexerciciosGinasio { get; set; }
[Required]
[Column("nome")]
[StringLength(30)]
public string Nome { get; set; }
[Required]
[Column("texto_descritivo")]
[StringLength(1000)]
public string TextoDescritivo { get; set; }
[Required]
[Column("foto")]
public string Foto { get; set; }
[Required]
[Column("video")]
public string Video { get; set; }
[InverseProperty("IdexerciciosGinasioNavigation")]
public virtual ICollection<Inclui> Inclui { get; set; }
}
}
In the controller belonging to the Exercises class (ExercisesController) I have this method in order to create a new exercise
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("IdexerciciosGinasio,Nome,TextoDescritivo,Foto,Video")] ExerciciosGinasio exerciciosGinasio, IFormFile fotografia,IFormFile video)
{
string caminho = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
string caminho_completo = Path.Combine(caminho, nome_ficheiro);
FileStream fs = new FileStream(caminho_completo, FileMode.Create);
fotografia.CopyTo(fs);
exerciciosGinasio.Foto = caminho_completo;
fs.Close();
string caminho2 = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro2 = Path.GetFileName(video.FileName);
string caminho_completo2 = Path.Combine(caminho2, nome_ficheiro2);
FileStream _fs = new FileStream(caminho_completo2, FileMode.Create);
video.CopyTo(_fs);
exerciciosGinasio.Video = caminho_completo2;
_fs.Close();
if (ModelState.IsValid)
{
_context.Add(exerciciosGinasio);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(exerciciosGinasio);
}
And in the view of this method I have
#model WebApplication1.Models.ExerciciosGinasio
#{
ViewData["Title"] = "Create";
}
<h4>Criar Exercicio</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Nome" class="control-label"></label>
<input asp-for="Nome" class="form-control" />
<span asp-validation-for="Nome" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TextoDescritivo" class="control-label"></label>
<input asp-for="TextoDescritivo" type="text" class="form-control" />
<span asp-validation-for="TextoDescritivo" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<input asp-for="Foto" type="file" class="form-control" accept=".png, .jpg, .bmp" value="" />
#*<span asp-validation-for="Foto" class="text-danger"></span>*#
<div>
<input type="hidden" name="fotografia" value="0" />
</div>
<div class="form-group">
<label asp-for="Video" class="control-label"></label>
<input asp-for="Video" type="file" class="form-control" />
#*<span asp-validation-for="Video" class="text-danger"></span>*#
</div>
<div>
<input type="hidden" name="video" value="0" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<br />
<div>
<a asp-action="Index" asp-controller="Home">Voltar</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Does anyone know what may be causing this error? And how can I solve
NullReferenceException: Object reference not set to an instance of an object.
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
In your View page, we can find you are using hidden field(s) with default value 0 for fotografia and video, but your Create action expects file via IFormFile object, if you debug your code, you would find fotografia is null, which would casue exception while you read FileName property of fotografia.
To fix it, you can modify the code like below.
Inputs of Photo and Video
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<input type="file" class="form-control" name="fotografia" accept=".png, .jpg, .bmp" />
</div>
<div>
<input type="hidden" name="Foto" value="0" />
</div>
<div class="form-group">
<label asp-for="Video" class="control-label"></label>
<input type="file" name="fvideo" class="form-control" />
</div>
<div>
<input type="hidden" name="Video" value="0" />
</div>
Controller Action
[HttpPost]
public IActionResult Create([Bind("IdexerciciosGinasio,Nome,TextoDescritivo,Foto,Video")] ExerciciosGinasio exerciciosGinasio,
IFormFile fotografia,
IFormFile fvideo)
{
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
//code logic here
return View(exerciciosGinasio);
}
Test Result
I have an exercise class and a view that allows me to create exercises.
One of the variables is a video, how can you insert a video in order to save it in the database and present it in the view?
In exercise class I have
[Table("Exercicios_Ginasio")]
public partial class ExerciciosGinasio
{
public ExerciciosGinasio()
{
Inclui = new HashSet<Inclui>();
}
[Key]
[Column("IDExercicios_Ginasio")]
public int IdexerciciosGinasio { get; set; }
[Required]
[Column("nome")]
[StringLength(30)]
public string Nome { get; set; }
[Required]
[Column("texto_descritivo")]
[StringLength(1000)]
public string TextoDescritivo { get; set; }
[Required]
[Column("foto")]
public string Foto { get; set; }
[Required]
[Column("video")]
public string Video { get; set; }
[InverseProperty("IdexerciciosGinasioNavigation")]
public virtual ICollection<Inclui> Inclui { get; set; }
}
}
In the controller Exercises I used the function Create automatically generated in the creation of the controller
In the method I added code to save the image in the database
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("IdexerciciosGinasio,Nome,TextoDescritivo,Foto,Video")] ExerciciosGinasio exerciciosGinasio, IFormFile fotografia,IFormFile video)
{
string caminho = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
string caminho_completo = Path.Combine(caminho, nome_ficheiro);
FileStream fs = new FileStream(caminho_completo, FileMode.Create);
fotografia.CopyTo(fs);
exerciciosGinasio.Foto = caminho_completo;
fs.Close();
string caminho2 = Path.Combine(_hostEnviroment.ContentRootPath, "wwwroot\\Exercicios");
string nome_ficheiro2 = Path.GetFileName(video.FileName);
string caminho_completo2 = Path.Combine(caminho2, nome_ficheiro2);
FileStream _fs = new FileStream(caminho_completo2, FileMode.Create);
video.CopyTo(_fs);
exerciciosGinasio.Video = caminho_completo2;
_fs.Close();
if (ModelState.IsValid)
{
_context.Add(exerciciosGinasio);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(exerciciosGinasio);
}
So how do I put it in the view to insert a video and save it in the database?
In order to be able to present it in the index
#model WebApplication1.Models.ExerciciosGinasio
#{
ViewData["Title"] = "Create";
}
<h4>Criar Exercicio</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Nome" class="control-label"></label>
<input asp-for="Nome" class="form-control" />
<span asp-validation-for="Nome" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TextoDescritivo" class="control-label"></label>
<input asp-for="TextoDescritivo" type="text" class="form-control" />
<span asp-validation-for="TextoDescritivo" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Foto" class="control-label"></label>
<input asp-for="Foto" type="file" class="form-control" accept=".png, .jpg, .bmp" value="" />
#*<span asp-validation-for="Foto" class="text-danger"></span>*#
<div>
<input type="hidden" name="fotografia" value="0" />
</div>
<div class="form-group">
<label asp-for="Video" class="control-label"></label>
<input asp-for="Video" type="file" class="form-control" />
#*<span asp-validation-for="Video" class="text-danger"></span>*#
</div>
<div>
<input type="hidden" name="video" value="0" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<br />
<br />
<br />
<br />
<div>
<a asp-action="Index" asp-controller="Home">Voltar</a>
</div>
<br />
<br />
<br />
<br />
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
I tested it this way, and I got this error
NullReferenceException: Object reference not set to an instance of an object.
WebApplication1.Controllers.ExerciciosGinasiosController.Create(ExerciciosGinasio exerciciosGinasio, IFormFile fotografia, IFormFile video) in ExerciciosGinasiosController.cs, line 64
WebApplication1.Controllers.ExerciciosGinasiosController.Create(ExerciciosGinasio exerciciosGinasio, IFormFile fotografia, IFormFile video) in ExerciciosGinasiosController.cs
string nome_ficheiro = Path.GetFileName(fotografia.FileName);
Can someone help me solve it?
I have a form with all fields, less one of it, filled from user. This is the class passed through the form
public class CarForm {
private String id;
private Integer initialKm;
private String carChassis;
private String note;
private String carType;
private Integer fleet;
The only one field, fleet, I would like to set before pass the form, or better, set it from HTML. For example:
<div class="form-group">
<label>Fleet application</label> <input type="text"
class="form-control" th:field="*{fleet}"
th:placeholder="${fleetApplication}" readonly="readonly">
</div>
So I would like to show ${fleetApplication.application} and set into fleet this value, or, if it is possible, set another value${fleetApplication.idFleet}.
Is it possible one of these solutions?Thanks
Update: as suggested by #Faraj Farook I resolved so:
<div class="form-group">
<label>Fleet application</label>
<!-- Show fleet application -->
<input class="form-control" type="text" th:value="${fleetApplication.application}" readonly="readonly" />
<!-- Save into fleet the value of idFleet -->
<input type="hidden" name="fleet" th:value="${fleetApplication.idFleet}" />
</div>
Setting it in the server side
controller
String action(Model model){
CarForm carForm = new CarForm();
carForm.setFleet(<some value>);
model.addAttribute("obj", carForm);
return view.html;
}
view.html
<div class="form-group">
<label>Fleet application</label>
<input type="text" th:field="*{fleet}" readonly/>
</div>
setting it in the client side
view.html
<div class="form-group">
<label>Fleet application</label>
<input type="text" readonly th:value="${someValueVariable}"/>
<input type="hidden" name="fleet" th:value="${someValueVariable}"/>
</div>