I'm usinge a 3rd Party file uploader(Backload)to upload images & JavaScript to get the uploaded image names.I want to bind that list of Image Names into my MVC model. My requirement is to create hidden inputs dynamically when I submit the form. I know , I have to use sequential binding here with a loop. Can anyone help me how to use proper syntax to achieve this.
It should be something similar to this
for (int i= 0; i< noOfImages; i++)
{
<input type="hidden" name="Model.Images[i].Name" value=file.name />
}
(please note that I don't want Ajax solution for this and please show me code to use in my Razor view or if there is another better solution please let me know).Thanks.
public class ItemModel
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<ImageModel> Images { get; set; }
}
public class ImageModel
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ItemModel Items { get; set; }
}
I use following JavaScript code to get the values of Uploaded File Name and to create hidden inputs when I click submit button of #ItemCreate form.
$('#ImageUplodedtable input[name="ImageName"]').each(function () {
$('#ItemCreateForm').append('<input name="ImageName" value="' + this.value + '"/>');
I'm adding the below part to my question. I missed single quotes and two plus signs ['+i+'] now it's working fine.
$('#ImageUplodedtable input[name="ImageName"]').each(function () {
for (int i= 0; i< noOfImages; i++)
{
<input type="hidden" name="Images[+'i'+].Name" value="' + this.value + '" />
}
I can't use .each() with for loop here.Can anyone suggest a way to get all the Image Names in Uploded table?
You've done it right in your for loop at the top, but once you get to the JavaScript portion, you're bungling the names. Keep the names of the input in the same style as the first for loop and you'll be fine, i.e. Images[N].Name where N is the index of the item in the collection.
I finally decided to use this function to create hidden files. I hope this may help a newbie like me in the future .
function CretaeHiddenFields(){
var uploadedImages = $('#ImageUplodedtable input[name="ImageName"]') ;
var divArea = $(#CreateInputDiv);
for (var i = 0; i < uploadedImages .length; i++) {
var imageName = document.createElement("input");
imageName.type = "hidden";
imageName.name = "Images[" + i + "].Name";
imageName.value = uploadedImage[i].value; // value of #ImageUplodedtable ImageNameinputs
formCreteItm.append(imageName);
}
}
Related
I am trying to scrape the web page with C# and I am using HtmlAgilityPack it works good for me, but I got an issue with this website when I need to scrape data from another page of product list. Because link doesn't have page number so I cannot access it by changing link. I found out that page is changed by javascript "__doPostBack" function which doesn't changes the link, just reloads the page, and loads the data.
This is my code for scraping code and price of the product in this web site, however there are more products in other page e.g 2, 3, 4, 5... I need to scrape data from all of these. On other websites I can do just simply passing link to web.Load("Link"); and it works well because link is changing when you change page of product list. In this example link is not changing when other page of the list is selected.
public class CodeAndPrice
{
public string Code { get; set; }
public string Price { get; set; }
}
public partial class Form1 : Form
{
DataTable table;
HtmlWeb web = new HtmlWeb();
public Form1()
{
InitializeComponent();
InitTable();
}
private void InitTable()
{
table = new DataTable("DataTableTest");
table.Columns.Add("Code", typeof(string));
table.Columns.Add("Price", typeof(string));
dataGridView.DataSource = table;
}
private async Task<List<CodeAndPrice>> DataScraping (){
var page = await Task.Factory.StartNew(() => web.Load("https://www.kilobaitas.lt/Kompiuteriai/Plansetiniai_(Tablet)/CatalogStore.aspx?CatID=PL_626"));
var codesNodes = page.DocumentNode.SelectNodes("//td[#class='mainContent']//div[#class='itemNormal']//div[#class='itemCode']");
var pricesNodes = page.DocumentNode.SelectNodes("//td[#class='mainContent']//div[#class='itemNormal']//div[#class='itemCode']//parent::div//div[#class='itemBoxPrice']");
if (codesNodes == null || pricesNodes == null)
return new List<CodeAndPrice>();
var codes = codesNodes.Select(node => node.InnerText.Replace("kodas", "").Replace(" ", "").Replace(": ", ""));
var prices = pricesNodes.Select(node => node.InnerText.Replace(" ", "").Replace(" €", ""));
return codes.Zip(prices, (code,price)=> new CodeAndPrice() { Code = code, Price = price }).ToList();
}
private async void Form1_Load(object sender, EventArgs e)
{
var results = await DataScraping();
foreach (var rez in results) {
table.Rows.Add(rez.Code, rez.Price);
}
}
}
Passing __doPostBack('designer1$ctl11$ctl00$MainCatalogSquare1$XDataPaging1','paging.1'); into the browser's console, page 2 is loaded, by changing "paging.*", browser loads page *+1
What is the simplest way to manipulate javascript, that I will be able to change page while scraping data and scrape data from other pages of this website?
I have been capturing user signatures using signature pad (https://github.com/szimek/signature_pad/). I need to be able to convert these signatures into a jpeg that retains the image of the signature. I can't get it to work with out the images just being a big black box. I think it has something to do with how the images are rendered.
I used this tutorial to create the signatures (https://www.thewebflash.com/using-signature-pad-with-asp-net-mvc/). I need the signature in a picture format so I can put it on my form. I'm guessing something is going wrong because javascript is needed to render the byte[] correctly, so I'm not converting the raw byte[] to a jpeg correctly in the controller (last part).
Here is my code:
Class:
public class Signature
{
public int ID { get; set; }
[UIHint("SignaturePad")]
public byte[] MySignature { get; set; }
}
public class SignatureDbContext : DbContext
{
public DbSet<Signature> SignatureDatabase { get; set; }
}
UIHint attribute in order to specify that the following SignaturePad.cshtml templates should be used to display the model property in a view.
Views\Shared\DisplayTemplates\SignaturePad.cshtml :
#model byte[]
<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear- canvas">Clear</button>
#Html.HiddenFor(model => model, new { #disabled = "disabled" })
and Views\Shared\EditorTemplates\SignaturePad.cshtml :
#model byte[]
<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear-canvas">Clear</button>
#Html.HiddenFor(model => model, ViewData["htmlAttributes"])
In my css Content\Site.css I have this :
.signature-pad > canvas {
display: block;
width: 300px;
height: 150px;
margin-bottom: 5px;
}
In the scripts folder I have a javascript script to help render the image on the view.
SignaturePadInit.js :
var signaturePadWrappers = document.querySelectorAll('.signature-pad');
[].forEach.call(signaturePadWrappers, function (wrapper) {
var canvas = wrapper.querySelector('canvas');
var clearButton = wrapper.querySelector('.btn-clear-canvas');
var hiddenInput = wrapper.querySelector('input[type="hidden"]');
var signaturePad = new SignaturePad(canvas);
// Read base64 string from hidden input
var base64str = hiddenInput.value;
if (base64str) {
// Draws signature image from data URL
signaturePad.fromDataURL('data:image/png;base64,' + base64str);
}
if (hiddenInput.disabled) {
signaturePad.off();
clearButton.classList.add('hidden');
} else {
signaturePad.onEnd = function () {
// Returns signature image as data URL and set it to hidden input
base64str = signaturePad.toDataURL().split(',')[1];
hiddenInput.value = base64str;
};
clearButton.addEventListener('click', function () {
// Clear the canvas and hidden input
signaturePad.clear();
hiddenInput.value = '';
});
}
});
When I want to see the signature in a view I include this at the buttom or else the signature appears as an empty white box:
#section Scripts {
<script src="~/Scripts/signature_pad.min.js"></script>
<script src="~/Scripts/SignaturePadInit.js"></script>
}
The signature_pad.min.js comes default with the signaturepad library through nuget. I didn't touch it and I don't think it needs to be discussed. I haven't included it because it is extremely long.
Here is my code for converting the byte[] to a jpeg. It converts the byte[] to a jpeg and adds it to a pdf but I have excluded everything but the part that converts to a jpeg. even saving the image locally yeilds a file that is a black block with no signature :
public ActionResult GeneratePDFforSignature(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Signature signature = db.SignatureDatabase.Find(id);
Image x = (Bitmap)((new ImageConverter()).ConvertFrom(signature.MySignature));
System.Drawing.Image img = x;
img.Save(Server.MapPath("~/Content/test.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
//return View();
return RedirectToAction("Index");
}
I really dont know what to do next to fix this and get the signatures as a jpeg with an actual image in it. I guess I'll keep messing with the SignaturePadInit.js for now. If anyone needs me to post more information to fix this please let me know in the comments.
Just a stab here, but have you tried to see if rendering to 24bit png will work allowing for areas that have no image/ signature be transparent?
I only think this because I had similar issues where there were encoded pixels for transparency that I wasn't thinking about and it had the same issue. (Would have commented but the system won't let me )
I am dynamically creating my html checkboxes at runtime using javascript/jquery like this. It's using the Jquery bootgrid.
isAssigned: function (column, row) {
if (row.isAssigned == "True" || row.isAssigned == "true") {
return "<input id='chk" + row.id + "' type='checkbox' name='chkMarks' checked='" + row.isAssigned + "' />";
}
else {
return "<input id='chk" + row.id + "' type='checkbox' name='chkMarks'/>";
}
}
What I need to do is somehow get the values in my submit buttons click event in the aspx.cs code behind. I cannot runat="server" these controls because the id is not added until after the page has loaded. I need to get the id's and whether they are true or false.
I was wondering if anyone knew the best approach for me to get these values in something like this.
protected void myTester_Click(object sender, EventArgs e)
{
var values = Request["chkMarks"].ToString();
}
You almost had it! You need to use Request.Form instead of just Request. That should give you access to all your DOM elements.
var values = Request.Form["chkMarks"].ToString();
Here is some more information on it: https://msdn.microsoft.com/en-us/library/system.web.httprequest.form(v=vs.110).aspx
Request.Unvalidated["chkMarks"]
can also be useful depending on what the value of this field is.
I did it using JSON in the end using a postback so not asynchronous which is hopefully useful to someone.
function BuildJSON() {
var jsonObj = [];
jQuery("input[name='chkMarks']").each(function () {
item = {}
item["id"] = this.id;
item["isAssigned"] = this.checked;
jsonObj.push(item);
});
var json = JSON.stringify(jsonObj);
$('#<%= hiddenMarksID.ClientID %>').val(json);
}
In the code behind I attached an event to button and picked up the JSON like so...
protected void btnSubmitMarks_Click(object sender, EventArgs e)
{
string json = hiddenMarksID.Value;
List<ChkMark> chkMark = new JavaScriptSerializer().Deserialize<List<ChkMark>>(json);
Here is the POCO...
public class ChkMark
{
public string id { get; set; }
public bool isAssigned { get; set; }
}
I'm using ASP to look for the selected value in a dropdown box. The dropdown box choices are generated at load time. Here is the JavaScript for that:
function CreateDepartmentDropdown(data) {
var dropdown = document.getElementById("department_dropdown");
for (var i = 0; i < data.length; i++) {
var array = data[i].split(',');
var option = document.createElement("option");
option.value = array[0];
option.innerHTML = array[1];
dropdown.add(option);
}
}
And it looks like this:
Looks fine to me. Then I checked the HTML out too just to be sure:
That looks great too. Now here is where the issue comes up. When I press submit this delegate fires in C# (still only testing while making this):
void Activity_Submit_Click(object sender, EventArgs e)
{
int fye = Int32.Parse(fye_dropdown.Value);
String activity_name = activity_name_field.Value;
String activity_responsible = responsible_field.Value;
int department = Int32.Parse(department_dropdown.Value);
String activity_start = datepicker_start.Value;
String activity_end = datepicker_end.Value;
}
And when I debug this it stops at department saying that it's malformed. Looking at department_dropdown.Value in the immediate window turns up an empty string and the dropdown itself has 0 children.
Why would this return an empty response when the list is clearly there? How would I go about fixing this?
The client-side items won't get posted back to the server like this.
The easiest way is to Serialize the array as Json, put it in a hidden input element's value :
In your markup:
<asp:HiddenField runat="Server" ID="department_dropdown_items" cssclass="department_dropdown_items" />
<asp:HiddenField runat="Server" ID="department_dropdown_selected" cssclass="department_dropdown_selected" />
Your Javascript:
function CreateDepartmentDropdown(data) {
var dropdown = document.getElementById("department_dropdown");
for (var i = 0; i < data.length; i++) {
var array = data[i].split(',');
var option = document.createElement("option");
option.value = array[0];
option.innerHTML = array[1];
dropdown.add(option);
}
$(".department_dropdown_items").text(JSON.Stringify(data));
}
$(document).ready(function() {
$("form").submit(function(e) {
$(".department_dropdown_selected").text( $("#department_dropdown").value);
});
});
then use it in the code behind:
void Activity_Submit_Click(object sender, EventArgs e)
{
string[] data = new JavascriptSerializer().Deserialize<string[]>(department_dropdown_items.Value);
string selectedValue = department_dropdown_selected.Value;
int fye = Int32.Parse(fye_dropdown.Value);
String activity_name = activity_name_field.Value;
String activity_responsible = responsible_field.Value;
int department = Int32.Parse(department_dropdown.Value);
String activity_start = datepicker_start.Value;
String activity_end = datepicker_end.Value;
}
The code is not tested. Tell me if it's not working :)
So I ended up doing the following:
Make a Hidden asp element called department_dropdown_selected_value
Then in a Script tag I made the following function:
.
function GetDepartmentDropdownValue(sel) {
var hidden_field = document.getElementById('department_dropdown_selected_value');
hidden_field.value = sel.value;
}
Then in my HTML I did this: <select class="form-control" id="department_dropdown" onchange="GetDepartmentDropdownValue(this)">
Then I can just simply do this in C#: int department = Int32.Parse(department_dropdown_selected_value.Value);
I have made a web user control (.ascx) which consists of the two html textbox and two input buttons, when I try to do document.getElementById('<%=ControlID.ClientID%>') it returns null. what could i have done wrong ?
source code:
<script language="javascript" type="text/javascript">
function intilize() {
var x = document.getElementById('<%=JSNumeric_Control.ClientID%>');
}
</script>
<table class="style1">
<tr>
<td >
<My:UserInfoBoxControl ID="JSNumeric_Control" runat="server" />
</td>
<td>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<input id="Button1" type="button" value="button" onclick="intilize()" /><br />
</td>
</tr>
</table>
Here is the code for the Numbric.cs, the following are the property used and in page load i am using JavaScript to assign all the events for the HTML inputs:
public partial class NumricCounter : System.Web.UI.UserControl
{
public string defualtValue = "0";
public double defaultIncrementValue = 1;
public int defaultPrecsionValue = 0;
public string Button_Add_ClientID
{
get { return Button_Add.ClientID; }
}
public string Button_Subtract_ClientID
{
get { return Button_Subtract.ClientID; }
}
//Set and Get for all these properties. (Code Omitted)
public string Text;
public double IncrementValue;
public int PrecsionValue;
public void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Text_Output.Value = this.Text;
Button_Add.Attributes.Add("onclick", "Add(" + IncrementValue.ToString() + "," + PrecsionValue.ToString() + ");");
Button_Subtract.Attributes.Add("onclick", "Subtract(" + this.IncrementValue.ToString() + "," + this.PrecsionValue.ToString() + ")");
Text_Output.Attributes.Add("onkeyup", "check(" + this.PrecsionValue.ToString() + ");");
}
}
}
Try replacing your function:
function intilize() {
var x = document.getElementById('<%=JSNumeric_Control.ClientID%>');
}
with this:
function intilize() {
var x = document.getElementById('JSNumeric_Control');
}
The getElementById should read the ID of the element from the rendored html.
JSNumeric_Control.ClientID will return the ClientID of the control if it were rendered to the page. It's existance doesn't necessarily mean that there will be HTML on the final page that has that ID.
For example if you create a control that just outputs two buttons you will give each of those buttons different IDs that are not the same as the control that they live in. Often you might create a container div that you will put around all other content which you will give the ID of the Control to for easy finding but there is no reason for this to exist.
What you should do is either make sure that your control does create this HTML container with the ID of your control or you should refer specifically to the client ID of the items inside your control.
var button1 = document.getElementById('<%=JSNumeric_Control.Button1.ClientID%>');
The problem is that in the DOM there's no element with Id = ClientID of your UserInfoBoxControl. The controls inside your user control will have other Ids, like 'JSNumeric_Control_Button1', 'JSNumeric_Control_TextBox1' etc. If you need to get both of the input buttons, you can do one of the following:
Use jquery selector to find all inputs with type = button and id starting with <%=JSNumeric_Control.ClientID%>
Add two new properties to your control - FirstButtonClientID and SecondButtonClientID that will provide you with clientIDs of your buttons. Then you can use it in javascript.
Create custom javascript object which will represent your usercontrol and provide necessary functionality.
You are most likely trying to search the DOM before it's been loaded. Try putting your code inside an onload handler:
document.onload = function () {
alert(document.getElementById('<%=ControlID.ClientID%>'));
}
This makes sure that the code isn't executed before you actually have all of the DOM loaded.
//Button_Add is the control id inside the user control
var x = document.getElementByID(JSNumeric_Control.FindControl("Button_Add").ClientID);