I've been working on a small school project and decided to use .net core (MVC) for the first time. I have a small button I can click which executes the "ipconfig" command in the background and displays the output in a text area. At first my team partner used only a
public string Result;
in ViewModel for the view. In the view it's displayed via
<textarea asp-for="Result"></textarea>
So I decided to make it into a property with default get and set:
public string Result { get; set; }
But when I do that, the output doesn't show up in the textarea if I keep the same approach in the view as my team member did when he used a field instead of a property. Instead I have to do it like this to get it to show up in the textarea:
<textarea>#Model.Result</textarea>
Now I'm asking myself why this happens. Can't I display Properties with asp-for? And what would be better to use, a field or a property as Result?
Many thanks in advance!
In my case this behavior was happening because I did not have a separate closing tag on my textarea. I know your example above has it when using the asp-for method, but in case that was a copy/paste error, you may want to look at that again.
<textarea asp-for="Message" type="text" class="form-control" rows="5" id="MessageInputField" autofocus></textarea>
As opposed to:
<textarea asp-for="Message" type="text" class="form-control" rows="5" id="MessageInputField" autofocus />
This is incredibly annoying 'gotcha' like behavior in my opinion. And maybe if someone wants to tell me why it isn't, then please enlighten me, I'm always willing to learn.
You should actually be using properties, and if <textarea>#Model.Result</textarea> works, <textarea asp-for="Result"></textarea> should as well. The only reason it wouldn't is if the ModelState has a different value for Result (as the latter form actually uses ModelState, whereas the former is obviously using Model directly).
ModelState is composed of values from Request, ViewData/ViewBag, and finally Model, so for example, if you were to do something like ViewBag.Result = String.Empty, that would actually override the value from Model in ModelState.
There's no enough code here to truly diagnose the exact issue, but I would look for other places you might be using "result" (case-insensitive). If you're accepting that as a request param or setting a ViewBag member, etc. that's your problem.
I find this is a bit weird in .Net Core 6, when I want two-way binding - ie displaying the result
With asp-for I have to self close the tag AND add the additional textarea close tag to get the result displayed.
<textarea asp-for="Result" />#Model.Result</textarea>
This works but is not syntactically correct.
Without the self-close tag, the result was not being display
<textarea asp-for="Result">#Model.Result</textarea> #*Does not display the value*#
For display only, this is more correct
<textarea>#Model.Result</textarea>
Related
I need to find the input box in this HTML:
<div id="employeesDataTable_filter" class="dataTables_filter">
<label>
<input type="search" class="form-control input-sm"
placeholder="Filter..." aria-controls="employeesDataTable">
</label>
</div>
But for the life of me cannot - please help,
I have successfully written bags of tests and found many page element of different types but this one has stumped me.
I am very new to this and have tried
By ExecutiveSearchBox = By.XPath("//input[#type='search' and
class='dataTables_filter']");
You have encountered problems because you are selecting class attribute on input node instead on div. Try following selector:
//div[#class='dataTables_filter']//input[#type='search']
Also as #Marco Forberg mention it is good to use contain() XPath function in case if there are multiple classes provided for element:
//div[contains(#class, 'dataTables_filter')]//input[#type='search']
I hope it'll help to resolve your issue :)
To find the input element in your html snippet, you simply use
FindElement( By.CssSelector( "input" ) )
But note:
not always is the input box editable after page load is completed, it may take some time. It might be wise to wait until the box becomes editable if you want to send data to it.
not always does the input box appear immediately in the DOM. With modern UI like Angular, it might be not there immediately, might be something else for a while and only later become an input field and the like. Also here, making use of Seleniums wait functionality sure is a good idea.
I ALWAYS wait for the DOM state I expect and only after some time when the state is not achieved I throw.
I need to get the value of an input and pass that to a select2 to get suggestions. How can I call a JavaScript function from a URL action
#* Name *#
<input id="Name" name="AccountName" type="text" value="" autocomplete="off" data-url="#Url.Action("*********", "******")" data-urlonselect="#Url.Action("*****", "*******")">
#* Group / HQ *#
#Html.Select2Ajax("newGroup", Url.Action("******", "****", new { valuefromInput = MyFunction(); }))
I have never used Select2, so there may be some functionality in there that I am unaware of. With that said, the Url.Action() is question is a standard part of the ASP.NET MC framework and I feel relatively comfortable with answering based on that.
Url.Action is a sever side razor directive. That means that all the processing happens on the webserver at the time of the request. It is not, nor can it be, aware of the JavaScript that may execute in the future.
My recommendation would be to create a hidden input, or a non-visible div, and store the output of Url.Action in that container, using a recognizable placeholder for your input value, say "-12." Then, in your javascript that is responding to the changes to the input, you can dynamically replace the place holder with its actual value and set that property accordingly on the select box. You may or may not need to re-initialize your Select2 drop down in with each call.
At least, that is why I would try. Hope this helps! =)
I have a C# MVC application and a <form> in my page.cshtml file. In that form I have <input type="text" ... /> elements. If I submit this form I only get the values in Response.Params or Response.Form from the inputs where I changed the value manually (i.e. Entered the text box then typed something).
If I change the value with jQuery, $('#myInput').val('some value'); this does not count as a change in the input's value and I do not get myInput's value when I submit the form.
Is there any way to make sure all inputs are submitted? If not then is there a good workaround for this, maybe in some event that occurs before my model gets bound? I need to know all the input values from the form when submitted whether they changed or not.
Some additional info:
The form and other values are getting submitted correctly and I am receiving my model when the POST action is called in my controller.
The real issue is when my model is being bound. It is being created and bound with all values except the one not being submitted because it is not in the Request.Params collection.
I have only ever seen this behaviour when a field is disabled. Due to this, I commonly have a javascript function that handles the form submission and re-enables them on submit, this way the correct values get sent to the server.
Something like this does the trick for me (NOTE: I am using JQuery):
$(document).ready() {
$("#ButtonSubmit").click(SubmitForm);
}
function SubmitForm(e) {
e.preventDefault();
//ensure fields are enabled, this example does text and checkbox types
$("[type='text']").attr("disabled", false);
$("[type='checkbox']").attr("disabled", false);
//submit the form
document.forms[0].submit();
}
I am unaware of any easier way to do this, it would be nice if you could 'flag' something that instructs all fields to be submitted. But I don't know if this exists, maybe somebody else can offer a better solution.
EDIT: It appears that disabled fields not submitting is just the nature of HTML, and is not something that is tied to MVC.
It seems that if you make the fields readonly instead of disabled then the values will still submit. However, with this approach you lose the 'disabled' styling. The exception to this rule is select control, it seems this will not submit under readonly either. More information on this can be in this question
Try using the razor helper to build the form tag.
#using(Html.BeginForm()) {
..
// make sure this is a submit button
<input type="submit" value="Save" />
}
In your controller action post method make sure you decorate it [HttpPost].
e.g.,
[HttpPost]
public ActionResult Edit(YourModel model) {
}
Im new at Asp.Net MVC3, and i was trying to use CKEditor. But can't get my typed text then i push submit.
My View:
<form method=post action="#Url.Action("Description")">
<textarea class="ckeditor" id="editor1" rows="10" name="Details">#Resources.Resources.DescriptionSampleText</textarea>
<input type="submit" />
</form>
And the controller there i need the text:
[HttpPost]
public ActionResult Description(string textdetails)
{
//Doing something with the text
return RedirectToAction("Create", "Project", new { text = textdetails});
}
What am I doing wrong?
There are three solutions to your problem. I will start of with solving it directly (two ways), however, in my opinion it is not the best way. Anyway, more about that later.
ASP.NET MVC (3) works a lot convention-based. It will magically assign values etc. from requests to parameters and other. Of course, these conventions are obviously based upon the names of your parameters. You'll have to make sure that your names match (as you might figure out right now, this will be a pain-in-the-a to maintain).
The quick solution is to name your textarea in your view the same as your parameter of your HttpPost action. Your view code would look like this:
<form method=post action="#Url.Action("Description")">
<textarea class="ckeditor" id="editor1" rows="10" name="Textdetails">#Resources.Resources.DescriptionSampleText</textarea>
<input type="submit" />
</form>
This should work. Note: I didn't test this myself right now, however many beginners guides do this as well, so I figure that will work. Anyway, I really don't like this solution, because it is really a hell to maintain (refactoring etc won't be very easy).
A second solution is to use a FormCollection. You give this as a parameter of your HttpPost action and you can access then your value through an index. For an example and more information, you can look at this SO post: https://stackoverflow.com/a/5088493/578843 .
The last solution (which I prefer) is creating a ViewModel. I suggest you read this guide ( http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/examining-the-edit-methods-and-edit-view ) on how to do edit pages etc properly.
And one last thing, if you want to submit HTML as content, you will have to either disable the save guarding of ASP.NET or add a Annotation to your method (or class). Please do not generally disable save guards (it will check input for html etc), only disable it with annotations when needed. You can set the ValidateInput attribute (MSDN link) to false on your action. Example:
[HttpPost]
[ValidateInput(false)]
public ActionResult Description(string textdetails)
{
//Doing something with the text
return RedirectToAction("Create", "Project", new { text = textdetails});
}
What's the best way to approach the following situation in asp.net mvc2 (c#):
I have a form where a user can add more fields ... for example I ask user the details of personal computing devices that they have. For simplicity sake let's say I ask for the brand and type (dropdown list of Desktop/Laptop/Tablet/Other) and they can provide unlimited devices. I will start with a pair of text boxes:
<label>Type</label>
<select><option>Desktop</option><option>Laptop</option><option>Tablet</option><option>Other</option></select>
<label>Brand</label>
<input type="text" />
<input type="button" value="Add more device" />
And then as user click the "Add more device" button I will display another pair of Brand and Type text boxes ... and so on.
My question is how should I use HTML helper for this, how I construct the viewModel, etc.
I am from PHP background and I used to use the following in PHP:
<input type="text" name="brand[]" />
which on the back end will give me an array of brands ... not sure if that's doable in asp.net environment. I would appreciate any input. Thank you.
[I added the following lines to make my question clearer]
I think I have not been very clear with my question.
Suppose I have the following viewmodel:
public class UserRegisterViewModel
{
public string DeviceBrand { get; set; }
public string DeviceType { get; set; }
}
That works well when I have two text boxes:
<%: Html.TextBoxFor(m => m.DeviceBrand) %>
<%: Html.TextBoxFor(m => m.DeviceType) %>
but the situation that I am facing is I need to allow user to add more pair of device brand and type text boxes ... user should be able to add as many as he needs to.
How should I write my viewmodel and view?
I hope this makes my question a bit clearer. I don't have problem in hiding and showing the text boxes (and yes I use JQuery for that).
Thank you.
In C#, like C++ arrays are fixed sizes. You can however use a List<> to do something similar. It allows you to dynamically add data with an add function. Like so:
List<object> name = new List<object>();
name.Add(an_object);
So say a list of strings:
List<string> myStrings == new List<string>();
myStrings.Add("Blah");
They're accessed just like arrays - Console.WriteLine(myStrings[0]) outputs Blah
Depending on scenarion there are following solutions:
If you already know which Textboxes will be shown add them in your page and set their visiblity to false (like in CSS "display:none") And show them later.
If you dont know in advance which textboxes will be shown you can still append them in HTML DOm (Add it to your page's controls collection)
To show them there are two apporaches:
In first case Either use jQuery or Javascript to show them back.
In first case Use can also do it from server side that will result in whole page post back.
In second Apporach Also you can use jQuery or Javascript to add new textboxes in the form
In second case you can add new boxes from your C# code on server but again it will result in whole page post back.
Use any approach that best suits you
What you can do is having UserRegister as Model and have UserRegisterViewModel
whith List property
Then in your view you can have loop to render your viewmodel list property
in a foreach for example in C#
Lets say you have your ViewModel defined as:
public class BrandListViewModel
{
public List<UserRegisterViewModel> Brands {get;set;}
}
Your View would need to output HTML as:
<select name="Brands[0].DeviceType">...</select>
<input type="text" name="Brands[0].DeviceBrand"/>
and
<select name="Brands[1].DeviceType">...</select>
<input type="text" name="Brands[1].DeviceBrand"/>
You need to keep the index going so that the model binder can construct your list in the correct order. Now, you could use jQuery to do this and as you append items to the page just get a count and increment by one. If you want to remove a single one, you need to rename all of the fields.
You could also use a pure jQuery method, parse the elements, push items to an array and send the array to the server.