asp.net mvc 4 data not binding - c#

i'm currently working on a use case where the user take a snapshot with his webcam, the snapshot is then displayed along with a form generated in javascript containing one hidden field (with the base64 code of the snapshot) and one submit button.
Problem is, the action do get called but the model is empty...I've been locked on this for multiple hours...
Datamodel :
namespace backend_OCR.Models
{
public class SnapshotModels
{
public string data_uri { get; set; }
}
}
Controller :
public ActionResult Capture()
{
ViewBag.uri = "URI_test";
return View();
}
[HttpPost]
public ActionResult Capture(SnapshotModels snapshot)
{
ViewBag.uri = snapshot.data_uri;
return View();
}
View :
#model backend_OCR.Models.SnapshotModels
#{
ViewBag.Title = "Capture";
}
<script type="text/javascript" src="~/Content/js/webcamjs.js"></script>
<div class="content-wrapper">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Camera</div>
<div class="panel-body">
<div class="container" id="my_camera"></div>
<!-- A form for taking snaps and processing them-->
<form style="text-align: center; margin-top: 10px;">
<input style="text-align: center;" type="button" class="btn btn-success" value="Prendre capture" onclick="take_snapshot()">
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Snapshot</div>
<h2>#ViewBag.uri</h2>
<div class="panel-body">
#using (Html.BeginForm("Capture", "Camera", FormMethod.Post))
{
<div id="results" style="text-align: center;">
L'image capturée apparaitra ici...
</div>
}
</div>
<br />
</div>
</div>
Javascript :
<script language="JavaScript">
Webcam.set({
width: 400,
height: 300,
image_format: 'jpeg',
jpeg_quality: 100
});
Webcam.attach('#my_camera');
</script>
<!-- Code to handle taking the snapshot and displaying it locally -->
<script language="JavaScript">
function take_snapshot() {
// take snapshot and get image data
Webcam.snap(function (data_uri) {
// display results in page
document.getElementById('results').innerHTML =
'<div><img id="my_snap" src="' + data_uri + '"/></div>'
+ '<input type="hidden" value="' + data_uri + '">'
+ '<input id="save" class="btn btn-success" value="Crop and send" type="submit"/>';
</script>

You didn't assign any ID/Name to your '<input type="hidden" value="' + data_uri + '">'
so the binder doesn't know how to bind it to your model and its property. it should have the same name/id your c# model class uses

For any other people also searching, make sure you do not have two or more inputs with the same name or that you have added the same input (using #HtmlHelper) twice, this will confuse the binder.

Related

Field not being found in view component

Ok So this works fine in a view model but when i move it out to a view component it doesnt.
#foreach (var notes in Model) {
<tr>
<td>#notes.LastModifedDate</td>
<td>#notes.LastModifiedBy</td>
<td>#notes.Notes </td>
<td>
<a class="btn btn-app">
<i class="fas fa-edit"></i> Edit
</a>
|<p>#notes.Id</p> <i class="glyphicon glyphicon-trash"></i>Delete
</td>
</tr>
}
This is my Model in the same view component
<div id="deleteLink" class="modal fade" role="dialog">
<div class="modal-dialog">
#using (Html.BeginForm("DeleteNotes", "MISObjects", FormMethod.Post)) {
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Delete Record!</h4>
</div>
<div class="modal-body">
Are you sure you wish to delete this record ?.
<!--this is how to pass the id through-->
<input type="text" name="linkId" id="linkId" />
</div>
<div class="modal-footer">
<button type="submit" id="btnSubmit" class="btn btn-danger"
onclick="$('#testForm').submit()">
Yes
</button>
<button class="btn btn-warning" data-dismiss="modal">No</button>
</div>
</div>
}
</div>
</div>
Here I am telling it to attach the notes Id here but for some reason its not finding the text field the notes id is being passed through the data-id="#notes.Id" of the button above.
#section Scripts
{
<script>
function deleteModal(id) {
alert(id);
$("#linkId").val(id);
}
function EditModal(id) {
$("#editMode").val(id);
}
</script>
}
I am getting the following error I presume this will be something to do with jquery not ready at this point.
Here is a worked demo to use view component:
TestViewComponent.cshtml:
#{
ViewData["Title"] = "TestViewComponent";
}
<h1>TestViewComponent</h1>
<div>
#await Component.InvokeAsync("Notes", new List<notes> { new notes { Id = "1", Notes = "note1", LastModifedDate = "2020/01/01", LastModifiedBy = "Joy" }, new notes { Id = "2", Notes = "note2" }, new notes { Id = "3", Notes = "note3" } })
</div>
#section Scripts
{
<script>
function deleteModal(id) {
alert(id);
$("#linkId").val(id);
}
function EditModal(id) {
$("#editMode").val(id);
}
</script>
}
Shared/Components/Notes/Default.cshtml:
#model IEnumerable<notes>
#foreach (var notes in Model)
{
<tr>
<td>#notes.LastModifedDate</td>
<td>#notes.LastModifiedBy</td>
<td>#notes.Notes </td>
<td>
<a class="btn btn-app">
<i class="fas fa-edit"></i> Edit
</a>
|<p>#notes.Id</p> <i class="glyphicon glyphicon-trash"></i>Delete
</td>
</tr>
}
ViewComponents/Notes:
public class Notes:ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(List<notes> list)
{
return View(list);
}
}
Result:
You should use jquery's event binding instead of on click.
First update your anchor tag by adding additional class.
<i class="glyphicon glyphicon-trash"></i>Delete
Then ensure that the #section Scripts block is on the main view not the partial view. Then bind the class using the following
<script>
$(window).on("load", function () {
$(".delete-notes").on('click', function () {
alert($(this).attr("data-id"));
});
function EditModal(id) {
$("#editMode").val(id);
}
})
</script>

Having issues with MVC

I currently have a form that when submit is clicked the selected value should be shown in the textarea/box and initial page should remain open.
But the problem I'm currently having is when I click the submit button, I'm being taken from the initial page and the value is being displayed on a blank page.
So basically I have two issues. How do I prevent being taken to another page once submit is clicked? And how can I get the value to be displayed in the textarea? I'm new to MVC, so any help would be greatly appreciated.
View:
<script language="JavaScript">
function showInput() {
document.getElementById('display').innerHTML =
document.getElementById("Envs").value;
}
</script>
<form asp-controller="CyberArk" asp-action="CyberArk" method="post" role="form" onsubmit="return confirm('Do you really want to carry out this action?');" id="form1" style="display:none;">
<div id="accordion" role="tablist" aria-multiselectable="true">
#* Form 1 *#
<div class="card">
<div class="card-header" role="tab" id="headingTwo">
<h5 class="mb-0">
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" style="font-size:15px;">
Vault Status
</a>
</h5>
</div>
<div id="collapseTwo" class="collapse" role="tabpanel" aria-labelledby="headingTwo">
<div class="card-block">
<div class="form-group">
<div class="form-group">
<p> This script returns status of vault servers for the chosen environment. It is used to determine if any servers overlap in order to detect a split brain.</p>
</div>
#model PAM_Dashboard_Project.Models.Vaults
#Html.DropDownList("Envs", new SelectList(Enum.GetValues(typeof(Envs))), "Select Enivronment", new { #class = "form-control" })
<br>
<div>
<button type="submit" onclick="showInput();">Submit</button>
</div>
<br />
<textarea class="form-control" cols="20" id="ouput1" name="output1" rows="2"></textarea>
</div>
</div>
</div>
</div>
</div>
</form>
Model:
public class Vaults
{
public string Envs { get; set; }
}
public enum Envs
{
RTPprod,
OMA,
BG1,
BG2,
Cloud,
Workstation,
QA
}
Controller:
public class CyberArkController : Controller
{
public IActionResult CyberArk()
{
return View();
}
[HttpPost]
public string CyberArk(Vaults newVault)
{
string SelectedValue = newVault.Envs;
return (SelectedValue);
}
}
Update your event attribute to:
onclick="showInput(event);"
Update your showInput method to:
function showInput(e) {
e.preventDefault();
document.getElementById('display').innerHTML = document.getElementById("Envs").value;
}
Note: You don't have an element with the id display, so you need to fix that.

Partial View not updating the razor value

I have a main page:
#model List<NovoRelatorioWeb.Controllers.HomeController.Campo>
#{
ViewBag.Title = "Relatorio";
}
<div id="RelatorioTablet">
<div class="container">
<div class="row">
<div class="col-lg-8">
<div class="row">
<div class="col-sm-12">
#if (Model != null)
{
<span>
Relatório ELO > Versão 2.0 > #Model[0].Relatorio
</span>
}
</div>
</div>
<hr style="border: 1px solid orangered" />
<div class="row">
<div class="col-sm-2">
<br />
<input type="button" id="butSalvar" class="form-control" style="background-color:orangered" value="Salvar" />
</div>
</div>
<hr style="border: 1px solid orangered" />
</div>
<div class="col-lg-4">
<div>
#Html.Partial("~/Views/Home/PhonePreview.cshtml", Model)
</div>
</div>
</div>
</div>
</div>
#section scripts {
<script src="~/Scripts/relatorio_elo.js" type="text/javascript"></script>
}
and it calls another page:
#model List<NovoRelatorioWeb.Controllers.HomeController.Campo>
#{
Layout = null;
}
<div>
<div id="PhonePreview" style="border:1px solid black;font-size:20px;">
#if (Model != null)
{
<div class="container1" style="background-color:orangered;padding-top:5px;padding-bottom:5px;">
<div class="row" style="text-align:center;width:100%;">
<div class="col-sm-12" >
<span style="color:white;">
#ViewBag.Relatorio
</span>
</div>
</div>
</div>
foreach (var campo in Model)
{
if (campo.Tipo == "Text")
{
#Html.Partial("~/Views/Home/Controles/Text.cshtml", campo)
}
}
}
</div>
</div>
<style>
input[type=date]::-webkit-inner-spin-button {
-webkit-appearance: none;
display: none;
}
</style>
and it calls
#model NovoRelatorioWeb.Controllers.HomeController.Campo
<div class="1" style="padding-top:5px;padding-bottom:5px;">
<div class="row">
<div class="col-sm-5">
<span style="padding-left:5px;">
#Model.Nome:
</span>
</div>
<div class="col-sm-7" style="text-align:right;">
<input type="text" style="width:100%;" />
</div>
</div>
</div>
and im calling the controller via jquery ajax
var urlService = "/Home/Salvar";
var jsonobj = CriaArrayCampos();
jsonobj = JSON.stringify(jsonobj)
$.ajax({
url: urlService,
type: 'POST',
data: jsonobj,
datatype: 'json',
contentType: 'application/json',
beforeSend: function () {
},
complete: function () {
}
});
It means, a page who calls a partial view, and a partial view inside. OIk, everything works, but when i click save button, i call the controller, who returns a list with objects to update the partial view (i only update the name).. But dont update.. but im making with razor... I have tested and the values comes to the partial view... how can i achieve this?
thanks so much!
Rafael

Embed Html `alert()` inside C# method call to display alert window MVC

I am trying to add Html code inside a #functions {} codeblock where if it matches some condition it will alert the user.
this is what I have so far, and I am getting the error CS0103: The name 'alert' does not exist in the current context
this is the code piece that is throwing the error.
#functions{
void doSomething(){
if(ViewBag.token != null){
#alert("#ViewBag.token");
}
}
}
Is there a way to embed alert() inside a C# code-block within .cshtml
this is the entire code which this function is in
#using System.Web.Mvc
#using System.Web.Mvc.Html
#using System
#using System.Web.UI
#model Dependency_Injection_MEF_MVC.Models.Payment
#section Scripts{
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
</script>
<script type="text/javascript">
$(function () {
var $form = $('#payment-form');
$form.submit(function (event) {
// Disable the submit button to prevent repeated clicks:
$form.find('.submit').prop('disabled', true);
// Request a token from Stripe:
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from being submitted:
return false;
});
});
function stripeResponseHandler(status, response) {
// Grab the form:
var $form = $('#payment-form');
if (response.error) { // Problem!
// Show the errors on the form:
$form.find('.payment-errors').text(response.error.message);
$form.find('.submit').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
ViewBag.token = token;
// Insert the token ID into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="Token">').val(token));
// Submit the form:
$form.get(0).submit();
}
};
</script>
}
<div class="row">
<div class="col-md-12 form-column">
<div class="form-container">
<form asp-controller="home" asp-action="processpayment" method="POST" id="payment-form">
<span class="payment-errors"></span>
<div class="form-group">
<h3>Membership Amount: USD XX</h3>
</div>
<div class="form-group">
<label for="cardNumber">Card Number</label>
<input class="form-control form-input" id="cardNumber" type="text" size="20" data-stripe="number" style= "width:250px;height:25px;font-size:120%">
</div>
<div class="form-group">
<label>Expiration (MM/YY)</label>
<div>
<input class="form-control form-input date-input" type="text" size="2" data-stripe="exp_month" style= "width:250px;height:25px;font-size:120%">
<input class="form-control form-input date-input" type="text" size="2" data-stripe="exp_year" style= "width:250px;height:25px;font-size:120%">
</div>
</div>
<div class="form-group">
<label for="cvc">CVC</label>
<input class="form-control form-input" id="cvc" type="text" size="4" data-stripe="cvc" style= "width:250px;height:25px;font-size:120%">
</div>
<input class="btn btn-default" onclick="doSomething()" id="submit" value="Submit Payment">
</form>
</div>
</div>
</div>
#functions{
void doSomething(){
if(ViewBag.token != null){
alert("#ViewBag.token");
}
}
}
Functions are intended to be completely server-side. But that script can be easily embeddable; if you move that to the page where you want it called, just do:
#if(ViewBag.token != null){
<script>
alert("#ViewBag.token");
</script>
}
And this will get rendered if the token exists. Functions aren't needed for this; this could be inside of a #helper though.

The id is missed when form is posted to controller

I am developing a mvc website.I have a table called member .this table has a controller and the controller has an edit method as you can see :
public ActionResult Edit()
{
int userId = _memberRepository.ReturnMemberIdByMobile(User.Identity.Name);
ViewBag.Edit = _memberRepository.FindById(userId).First();
return View();
}
[HttpPost]
public ActionResult Edit(Member value)
{
try
{
if (_memberRepository.Edit(value))
{
value.RegisteredDate = DateTime.Now;
_memberRepository.Save();
TempData["Success"] = "با موفقیت ویرایش شد ...";
string strLocation = HttpContext.Server.MapPath("~/Image/users");
if (value.ImgByte != null)
{
value.ImgByte.SaveAs(strLocation + #"\" + value.Id + ".jpg");
}
}
}
catch (Exception)
{
TempData["Error"] = "ویرایش نشد، لطفاً مجدداً تلاش نمایید";
}
return RedirectToAction("Edit");
}
The edit view is correctly work.the problem is when i post my view to edit controller .the id of member is changed to 0 it means it is missed.why ?and the value can't be edited.
#using DCL
#{
ViewBag.Title = "Edit";
Layout = "~/Areas/user/Views/Shared/_shared.cshtml";
Member membervalue = new Member();
membervalue = ViewBag.Edit;
}
#using (#Html.BeginForm("Edit", "User", FormMethod.Post,
new {id = "form", enctype = "multipart/form-data"}))
{
if (TempData["Error"] != null)
{
<div class="pad margin no-print">
<div class="callout callout-info" style="margin-bottom: 0 !important; background-color: #ea0000 !important; border-color: #d20000">
#TempData["Error"]
</div>
</div>
}
if (TempData["Information"] != null)
{
<div class="pad margin no-print">
<div class="callout callout-info" style="margin-bottom: 0 !important; background-color: orangered !important; border-color: red">
#TempData["Information"]
</div>
</div>
}
if (TempData["Success"] != null)
{
<div class="pad margin no-print">
<div class="callout callout-info" style="margin-bottom: 0 !important; background-color: #00A65A !important; border-color: #00925A">
#TempData["Success"]
</div>
</div>
}
<div class="row">
<!-- general form elements -->
<div class="col-xs-12">
<div class="box">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">حساب کاربری</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<div class="box-body">
<div class="col-lg-7">
<div class="input-group">
<label for="Name">نام</label>
<input class="form-control" id="Name" name="Name" type="text" value="#membervalue.Name">
</div>
<div class="input-group">
<label for="family">نام خانوادگی</label>
<input class="form-control" id="family" name="family" type="text" value="#membervalue.Family">
</div>
<div class="input-group">
<label for="mobile">موبایل</label>
<input class="form-control" id="mobile" name="mobile" type="text" value="#membervalue.Mobile">
</div>
<div class="input-group">
<label for="password">رمز عبور</label>
<input class="form-control" id="password" name="password" type="password" value="#membervalue.Password">
</div>
<div class="input-group">
<label for="Email">ایمیل</label>
<input class="form-control" id="Email" name="Email" type="text" value="#membervalue.Email">
</div>
<div class="form-group">
<label for="ImgByte">عکس </label>
<input id="ImgByte" name="ImgByte" type="file">
</div>
<input type="hidden" id="Id" name="id" value="#membervalue.Id">
</div>
</div>
<!-- /.box-body -->
</div>
</div>
</div>
<!-- /.box -->
</div>
<div class="row" style="margin: 0; margin-bottom: 20px">
<div class="box-footer" style="direction: ltr">
<button type="submit" class="btn btn-info">ویرایش</button>
<a class="btn btn-gray" href="#Url.Action("Index", "Home", null)">انصراف</a>
</div>
</div>
}
Instead of using the viewbag for your model you should pass in the model as a strongly typed object. You can do this with the following change in the Action. Then in your view define the model at the top and you can use it throughout the code.
You will also need a #Html.HiddenFor tag for your id. Now it is no longer possible (without a compile time exception that is) to create a type-o. On your previous code maybe you cased Id incorrectly which would cause it not to be populated OR maybe the form field name was not cased correctly. This takes all those manual errors out of the equation.
public ActionResult Edit()
{
int userId = _memberRepository.ReturnMemberIdByMobile(User.Identity.Name);
var model = _memberRepository.FindById(userId).First();
return View(model); // pass this in as the model, do not use viewbag
}
View
#model = Member #* namespace qualified type *#
#*... editor code *#
#Html.HiddenFor(x => x.Id)
#Html.TextboxFor(x => x.Name) #* do this instead of manual input *#
I ran your code, and there is no mistake in it. Id is passed correctly to Edit (post) action. The only reason it can be empty in the code that you show is that FindById returned entity without Id property set.

Categories

Resources