I'm having real troubles passing form data from a posting page made up of User Controls.
I posted this question before, here, Getting form field names on Submit when form is user control but the answers have not solved my problem, or I have mis-understood them.
Let me try explaining what I am doing more clearly.
I have a page which displays a form to the user. The form is made of several sections, but for simplicity we'll say there are two. Each of these sections is a User Control, thus the actual markup for newSale.aspx is just:
<%# Page Language="VB" MasterPageFile="~/MasterPage.master" CodeFile="newSale.aspx.vb" Inherits="newSale_Default"%>
<%# Register TagPrefix="controls" TagName="customerForm" Src="~/Controls/customerForm.ascx" %>
<%# Register TagPrefix="controls" TagName="itemList" Src="~/Controls/itemList.ascx" %>
<asp:content id="content1" ContentPlaceHolderID="mainContent" runat="server">
<div class="content">
<form id="newSale" method="post" action="saveSale.aspx">
<h1>--- New Sale ---</h1>
<div class="section" id="customerSection">
<controls:customerForm ID='customerForm1' showBankDetails="false" runat='server' />
</div>
<div class="section" id="saleSection">
<controls:itemList ID='itemList1' showShipping="false" showDeposit="false" runat='server' />
<div class="row submitRow">
<div id="submitSale">Submit</div>
</div>
</div>
</form>
</div>
</asp:content>
So you see my two main Controls tags with the IDs "customerForm1" and "itemList1" respectively.
The submit button is deliberately a clickable div and submission is done by jQuery, thus:
$('#submitSale').live('click', function () { $('#newSale').submit(); });
As the User Controls are rendered into the browser, the IDs and Names of the elements are messed about (I understand the reason why) by ASP.NET, so taking one field as an example:
A field named "name" contained within the customerForm control becomes m$mainContent$customerForm1$name
'm' - being the ID of my MasterPage
'mainContent' - being the ID of the PlaceHolder
'customerForm1' - being the ID of the User Control and
'name' being the element's actual name.
I wish to submit this form to a separate file (saveSale.aspx) as per the action attribute of my Form tag declared above.
Within the Code-Behind of saveSale.aspx I need to save the data passed from the form into a dataBase and return it in the aspx file as an HTML page.
How do I reliably get the value of the submitted form fields in saveSale.aspx(.vb)?
<%= request.form("m$mainContent$customerForm1$name") %>
Works, but naturally is a pain to use, especially when I want to replicate this to other purposes.
m.mainContent.customerForm1.name.selectedValue()
tells me that 'm' is not declared
and from the other replies to my previous question I have tried registering the controls at the top of the (saveSale.aspx) page, and explicitly posting the Control into the page again with
<controls:customerForm ID='customerForm1' showBankDetails="false" runat='server' />
Which doesn't work, but even if it did, it makes no sense anyway as I don't want to use the Control anymore, I just want to get the data from it.
I do apologise if I'm being dumb here, but I have tried so many different variations of code and Googled ideas, but I can't seem to make this work in any scalable fashion beyond the Request.Form example above.
I am using .NET 2.0 so can't use the Static Client feature that I've seen mentioned for .NET 4.0
Also, please, I am using VB.NET, so if you can help, please help with a VB example.
Many thanks.
Related
I just come across a good write up for a new ASP.NET Core feature called Tag helpers.
From there, I understood that one can replace the following code:
#model MyProject.Models.Product
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => p.Name, "Name:")
#Html.TextBoxFor(m => p.Name)
</div>
<input type="submit" value="Create" />
}
with:
#model MyProject.Models.Product
#addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
<form asp-controller="Products" asp-action="Create" method="post">
<div>
<label asp-for="Name">Name:</label>
<input asp-for="Name" />
</div>
<input type="submit" value="Save" />
</form>
There's some new syntax such as asp-controller, asp-for, etc. But what does it do? And what's the advantage of this new approach?
The most important improvement I've seen so far is the control it guarantees over your HTML elements. While convenient, the Html helpers used by MVC create problems when you try to do things they weren't built for.
A simple example can be seen when using the TextBox in MVC5:
#Html.TextBoxFor(m => p.Name)
The resulting HTML markup looks like:
<input class="form-control" id="Name" name="Name" type="text" value="">
Nice and simple. But what if you want to add a placeholder attribute? What if you want to use bootstrap's validation states? What if you have some 3rd party super cool javascript library which needs custom attributes. None of these things were possible in the initial release of MVC5. Though they were eventually added via update in the form of htmlAttributes. Even now adding custom attributes is kludgey at best.
#Html.TextBoxFor(m => p.Name,
new {#class="form-control has-error", placeholder="Enter Name",
superCoolFeature="Do something cool"})
While you could argue this is still less code that straight HTML, it is no longer a significant advantage. Worse, this solution still doesn't cover dashes in attributes which are fairly common. If you need them you are stuck with a workaround such as ActionLink htmlAttributes
I've gone down the route of fixing these deficiencies with custom editors, and tried building my own TextBox controls. It became obvious pretty quickly that replacing the included TextBox templates would require a lot of work. Worse, your templates have to have knowledge of any extensions you are adding to use them.
It seems like the inclusion of Bootstrap and other 3rd party tools into MVC have made it more obvious that the current design has problems with extending HTML which need to be fixed. Hopefully the tag helpers implementation is complete enough that we can avoid them in the future.
Not to mention, your Web Designers will have real HTML tags to edit that they recognize to re-design your pages. Designers shouldn't have to be coders and there's enough for these sharp folks to keep up with, studying the moving targets of HTML5 and CSS3 specs.
A few things come to mind:
As #ChrisWalter points out, these tag helpers give HTML tags an Open/Closed quality. Rather than just letting you write extension methods for common HTML patterns, you can extend an HTML element. This lets you pick-and-mix multiple extensions per component, rather than having to choose between them.
HTML Helpers tend to not work super well for elements that need to have inner HTML provided as an argument. They came up with a clever pattern so you can say:
#using (Html.BeginForm(...)){
{
<input ... />
}
But there's nothing about BeginForm() that would force you to put it in a using statement, and there's nothing to prevent you from using incorrect HTML structure. (<input> technically isn't allowed to be directly inside a <form> tag.)
This gives us a really easy transitional stepping stone into the Web Components world of HTML5. A component that you write today for jQuery or Bootstrap to pick up and enhance may make more sense as an Angular 2 or Polymer component in a few years. Using HTML syntax makes it possible to write your HTML the way you want it to look when it's a web component, and have it automatically translated into the structure it has to take on for now (or for specific browsers, later).
Accepted answer is correct but just a correction.
Html Helpers cover dashes in attributes by use of underscore. for example if you want html like
my-attr=value
then you can use html helpers like
#Html.TextBoxFor(m=>m.id,
new { my_attr = value })
then it will convert accordingly.
I know the original question asks about advantages but for the sake of completeness I have to mention one disadvantage:
With tag-helpers enabled you cannot inject C# code inside tag attributes.
I.e. this code will break:
<!-- this won't work -->
<input class="#GetMyClass()">
<!-- this won't work too -->
<input type="checkbox" #(condition ? "checked" : "") >
To work around this problem you can use custom tag helpers or just disable tag helpers altogether like described in this answer: https://stackoverflow.com/a/65281018/56621
P.S. My humble opinion that can be safely ignored: tag helpers are "magic". And "magic" is always bad in programming. If something looks like an HTML tag, walks like a tag and quacks like a tag - then it should probably be an HTML tag. Without me knowning "oh, it's not *really* a tag".
From building a basic web app from the ground up in .NET 7/Razor pages, I haven't encountered a single instance where a tag helper has an advantage over simply coding the HTML. I don't come from an MVC background so maybe that is where the advantage lies but as seen before...Microsoft has released yet another version of wheel-reinvention that instead of making things easier for some simply adds more confusion to others.
This is my first question. I am in stack overflow almost every day, but this is the first time I can't find the answer by myself and have to post it here.
I am creating pages with Ext.Net dynamically (in VB.net if it matters), based on a XML configuration, with all kind of controls and any number of them. So, for each field in the XML, I create the control and assign an ID to it (the ID is from the XML). I have a "submit" button that, when clicked, parse the XML again, get the ID of each field, and gets the control for this ID with Ext.Net.X.GetCmp. Then, once I have the control, I get the value and do some stuff with it. Everything works like a charm except for the control type FileUploadField. According to this, for some reason, GetCmp doesn't work with FileUploadField.
So, my question is: Is there some way to get a FileUploadField control based on it's ID? And, just to know, why GetCmp doesn't work with this kind of control?
Thank you very much in advance, and sorry for my bad english.
EDIT:
Ok, I have updated my Ext.Net to the latest version (2.2). Everything now looks strange, but it doesn't matter, if it works. Besides the appearance, I don't see any change in the behavior. GetCmp is still giving me the same. By the way, X.GetCmp(Of Ext.Net.FileUploadField)(ControlID) gives me a FileUploadField, not null, even if I don't create the control. The only thing, is that hasFile=false always, and the filebytes are empty.
EDIT 2:
I have run your example code and it works like a charm. I start thinking that the "isUpload" is the key. I Have been googling all the day trying to see where and why do I have to write this {isUpload=true}, but I didn't see anything useful. Can you explain it to me a little bit? Is only for DirectMethods? Is mandatory? Thanks a lot!
EDIT 3:
I feel sooooo stupid now. It works. Just added a simple isUpload:true in the DirectMethod call in a javascript. So many days to solve this stupid thing. For the next guy: check your isUpload ;).
So, my question is: Is there some way to get a FileUploadField control based on it's ID?
Only recreating that control. You render a control during one AJAX request (DirectEvent/DirectMethod) and it doesn't persist during another AJAX request unless you recreate it manually. It behaves the same as standard ASP.NET controls.
Controls can be recreated in Page_Init and must be recreated with the same IDs. In this case, a control's LoadPostData should extract a correct value from a POST collection. Here is a related discussion.
And, just to know, why GetCmp doesn't work with this kind of control?
It doesn't work in Ext.NET v1, but works in Ext.NET v2. Here is a sample below.
Though, it just extracts a file from the POST. X.GetCmp<>() returns a proxy control, it is not a real control. It is just a convenient way to extract POST values of dynamically rendered controls and, also, updates those controls on client (changing its properties and calling its methods).
<%# Page Language="C#" %>
<%# Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<script runat="server">
protected void RenderFileUploadField(object sender, DirectEventArgs e)
{
FileUploadField fileUploadField = new FileUploadField()
{
ID = "FileUploadField1",
Width = 300,
Listeners =
{
Change =
{
Handler = #"App.direct.GetFileName(this.id, {
isUpload : true
});"
}
}
};
this.Form.Controls.Add(fileUploadField);
fileUploadField.Render();
}
[DirectMethod]
public void GetFileName(string id)
{
X.Msg.Alert("FileName", X.GetCmp<FileUploadField>("FileUploadField1").PostedFile.FileName).Show();
}
</script>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />
<ext:Button
runat="server"
Text="Create a FileUploadField"
OnDirectClick="RenderFileUploadField" />
</form>
</body>
</html>
you could use simple javascript:
var fileinput = document.getElementById("fileinput");
as javascript does only search the DOM you need to be careful. each Ext.Net component will get a bunch of wrappers and sub-components and "unnecessary" siblings/parents/children (for header, label, bottom- and topbar and so on..)
if you have given an ID to the control you should be able to fetch it via:
App.{control-id}
this will return the constructor. you should be able to fetch FileBytes from ExtJS anytime using the App namespace (see BREAKING CHANGES)
the finished get for the FileBytes would look like this:
App.{control-id}.FileBytes
I am using ASP.NET MVC 4 HTML.BeginForm and it creates a validation-summary-errors class as
below. This doesn't fit with my layout. Is there a way that I can make it put the
validation div class in a different place?
<form action="/User/Account/Login" method="post" novalidate="novalidate">
<div class="validation-summary-errors">
<ul>
<li>The user name or password provided is incorrect.</li>
</ul>
</div>
<fieldset>
<legend>Local Login</legend>
<ol>
<li>ation-summary-errors in a different position?
Well, sure, it's up to you to put the #Html.ValidationSummary() helper call which generates this markup wherever you want. As far as controlling the exact markup that this helper spits, that would be much more difficult because this helper offers you almost no control over the generated markup.
If you need to have more control you could write a custom helper.
You can use #Html.ValidationMessage("validation-errors") and put it in any HTML tag and then can use CSS to give it a style.
Is there any way, like one does with WordPress, to create a header.php, theme-file.php and footer.php and then combine them using hooks? It seems crazy to me to still duplicate skin files especially when you need to make minor changes to the content of either a header or footer.
Many thanks
A skin is just an ascx control, so you can encapsulate parts of it just like you would any other WebForms view. You can put the header/footer content into their own ascx file, and then just include them in the skin. The only place you'll run into an issue with this is that I don't think DNN supports having panes in separate controls; everything else should be fair game.
You'll want to put them in a separate directory, so that they aren't seen as other skins by DNN.
-MySkin
--Controls
---Header.ascx
---Footer.ascx
--Home.ascx
--Home.doctype.xml
--Interior.ascx
--Interior.doctype.xml
Then, in the skins, include the controls by registering them in the header:
<%# Register TagPrefix="myskin" TagName="Header" Src="Controls/Header.ascx" %>
<%# Register TagPrefix="myskin" TagName="Footer" Src="Controls/Footer.ascx" %>
And include it via the control syntax:
<myskin:Header runat="server" />
....
<myskin:Footer runat="server" />
The control won't automatically have access to any context from the skin, so if you need to use SkinPath or PortalId or anything like that, you'll need to pass it through to the control manually. In the control, define a property to receive the value (using a <script runat="server"> section to write code [set the Language attribute in the control to C# for this]):
<script runat="server">
public string SkinPath { get; set; }
</script>
Then pass the value in the skin:
<myskin:Header runat="server" SkinPath="<%# SkinPath %>" />
I am using the rails 3 gem nested_forms and would like to change how the default blueprint for insertion is generated. I can not figure out how/where this code would comes from, and how/where I would add code to modify it.
I am currently using a partial for my form:
/app/views/units/_unit.html.haml
%tr
%td=f.text_field :units
%td=f.text_field :dispatched
%td=f.text_field :onscene
%td=f.text_area :actions
The code snippet that calls the partial:
/app/vies/reports/_form.html.haml
...
%table.units
%th Unit
%th Dispatched%th On Scene
%th Actions
=f.fields_for :units
%p= f.link_to_add "Add a unit", :units
...
I have all of the core functionality working, except for the template. That is auto created at run time by the gem. This template results in very simple HTML markup being used for the template.
Which is similar to the following:
<div id="units_fields_blueprint" style="display:none">
<p class="fields">
<input id="report_units_attributes_new_units_unit" name="report[units_attributes][new_units][unit]" size="30" type="text">
<input id="report_units_attributes_new_units_dispatched_1i" name="report[units_attributes][new_units][dispatched(1i)]" type="hidden" value="2011">
...
</p>
</div>
I would like the blueprint to have the tabular format that is in the partial, I just don't know how to get there.
Any help would be appreciated.
A partial which contains only a table row, such as listed above will not be valid markup when placed within the blueprint div.
The following code is not valid markup.
<div>
<tr>
<td>Content</td>
</tr>
</div>
Certain browsers (chrome for example) will attempt to correct this bad markup, which is done by stripping out the tr and td markup.
To get this type of code to work with nested_form would be complex requiring that the blueprint be created in a javascript string, and would require a modification to the builder to stop automatically surrounding inserted code in a block of code.
These changes are addressed in issue #73 for nested_form which refers to a branch created by the github user elmatou.
Another option to get a similar look and feel is to use divs and spans and create a grid structure using CSS. This is a CSS intensive process, but allows nested_form to be used without requiring alteration.