Upload file using knockout-file-bind - asp.net

I am trying to send a multipart form consist of text and file type using knockoutjs.
There is an error regarding data-bind file.
Here's my formView:
<div class="form-horizontal">
<div class="form-group">
<div class="col-md-12">
<label class="control-label">Supplier</label>
<input type="text" name="Supplier" id="Supplier" data-bind="value: Supplier" class="form-control col-md-8 form-control-sm" required />
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<label class="control-label">Picture</label>
<input type="file" name="fileInput" id="fileInput" data-bind="file: {data: fileInput, reader: someReader}" class="form-control" />
</div>
</div>
</div>
#section scripts {
<script src="~/Scripts/SDSScripts/RegisterSdsView.js"></script>
}
ViewModel:
function RegisterSdsView() {
var self = this;
self.Supplier = ko.observable();
self.fileInput = ko.observable();
someReader = new FileReader();
self.RegisterSds = function () {
if (self.errors().length > 0) {
self.errors.showAllMessages();
return;
}
var Supplier = self.Supplier();
var fileInput = self.fileInput();
$.ajax({
url: '/SdsView/RegisterSds',
cache: false,
type: 'POST',
data: {Supplier, fileInput},
success: function (data) {
//some code
},
error: function (data) {
//some code
}
});
}
}
ko.applyBindings(new RegisterSdsView());
Controller:
public ActionResult RegisterSds(string Supplier, HttpPostedFileBase fileInput)
{
var db = new SDSDatabaseEntities();
if (fileInput.ContentLength > 0)
{
string fileName = Path.GetFileNameWithoutExtension(fileInput.FileName);
string fileExtension = Path.GetExtension(fileInput.FileName);
string path = Path.Combine(Server.MapPath("~/UploadedFiles"), fileName);
fileInput.SaveAs(path);
var doc = new SDSDocument()
{
DocName = fileName,
DocType = fileExtension,
DocPath = path
};
db.SDSDocuments.Add(doc);
}
db.SaveChanges();
var result = new { status = "OK" };
return Json(result, JsonRequestBehavior.AllowGet);
}
The problem is the fileInput(viewModel) return null to my controller(HttpPostedFileBase fileInput).
Am I doing these the right way?
This is actually my very first C# .NET project. I can't seem to find a good example related to knockoutjs file data-bind. Basically how to POST Based64 to controller?
Here the api that I use https://github.com/TooManyBees/knockoutjs-file-binding

Well I solved it. I gonna update it here just in case. Basically I just have to POST Base64 string to controller via FormData. I don't know why my previous method cannot send large string value, maybe there are limitation on POST method or browser on how large you can send a data via AJAX.
Here is the reference https://stackoverflow.com/a/46864228/13955999

Related

Integrate Google Picker with MeteorJS

I am trying to use Google Picker within a Meteor application. I am not an expert, I just followed the example on Google Picker API page https://developers.google.com/picker/docs/index but could not make it work.
Here is what I tried in the client side and of course I changed the devKey and Client ID:
// The Browser API key obtained from the Google Developers Console.
var developerKey = 'AIzaSyC9gfrgtnj6fd00hDau3B0LSTqajeDIyl0';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = "582812345678-5t9joqkb5d1rfders25fhr5u6k28s9lc.apps.googleusercontent.com"
// Scope to use to access user's photos.
var scope = ['https://www.googleapis.com/auth/photos'];
var pickerApiLoaded = false;
var oauthToken;
Template.gPicker.helpers({
// Use the API Loader script to load google.picker and gapi.auth.
onApiLoad : function() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
},
onAuthApiLoad : function() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
},
onPickerApiLoad : function() {
pickerApiLoaded = true;
createPicker();
},
handleAuthResult : function(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
},
// Create and render a Picker object for picking user Photos.
createPicker : function() {
if (pickerApiLoaded && oauthToken) {
var picker = new google.picker.PickerBuilder().
addView(google.picker.ImageSearchView).
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
},
// A simple callback implementation.
pickerCallback : function(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
});
Then on the template:
<head>
<title>imagesearch</title>
</head>
<body>
{{> gPicker}}
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
<template name="gPicker">
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control recherche">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
</div>
</div>
<div id="result"></div>
</template>

File upload not working with angular and webmethod

I am basically trying to upload a file using angular and a webmethod.
I took the code from this blog but it does not work. The request is successfull as seen from fiddler but the web method never gets invoked.
Am I doing something wrong?
Following is my code .
angular
.module('loader', ['ui.router', 'ui.bootstrap', 'ui.filters'])
.controller('loader-main', function($rootScope, $scope, WebServices) {
$scope.uploadNewFile = function() {
WebServices.uploadFile($scope.myfile);
}
}).factory('WebServices', function($rootScope, $http) {
return {
postFile: function(method, uploadData) {
var uploadUrl = "myASPXPAGE.aspx/" + method;
return $http.post(uploadUrl, uploadData, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
}).success(function(data) {
///Control reaches here but never hits the server method
});
},
uploadFile: function(filedata) {
var fd = new FormData();
fd.append('file', filedata);
return this.postFile("UploadFile", fd);
}
};
}).directive('fileModel', ['$parse',
function($parse) {
return {
restrict: 'A',
link: function($scope, element, attr) {
var model = $parse(attr.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
$scope.$apply(function() {
modelSetter($scope, element[0].files[0]);
});
});
}
}
}
]);
<div class="row">
<div class="col-xs-5">
<div class="col-xs-4">Browse to File:</div>
<div class="col-xs-1">
<input type="file" id="uploadFile" class="btn btn-default" file-model="myfile" />
<input type="button" class="btn btn-primary" value="Load File" data-ng-click="uploadNewFile()" />
</div>
</div>
</div>
And here is my WebMethod
[WebMethod]
public static string UploadFile()
{
System.Diagnostics.Debugger.Break();
return "Done";
}
Figured it out. You cannot have Content-Type as multipart/form-data in webmethods. Instead created a HttpHandler to upload the file and everything works just fine.

Partial view render on button click

I have Index view:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<!DOCTYPE html>
<html>
<head>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<meta name="viewport" content="width=device-width" />
<title>MsmqTest</title>
</head>
<body>
<div>
<input type="submit" id="btnBuy" value="Buy" onclick="location.href='#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })'" />
<input type="submit" id="btnSell" value="Sell" onclick="location.href='#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })'" />
</div>
<div id="msmqpartial">
#{Html.RenderPartial("Partial1", Model); }
</div>
</body>
</html>
and partial:
#using System.Web.Mvc.Html
#model MsmqTestApp.Models.MsmqData
<p>
Items to buy
#foreach (var item in Model.ItemsToBuy)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
<p>
<a>Items Selled</a>
#foreach (var item in Model.ItemsSelled)
{
<tr>
<td>#Html.DisplayFor(model => item)
</td>
</tr>
}
</p>
And controller:
public class MsmqTestController : Controller
{
public MsmqData data = new MsmqData();
public ActionResult Index()
{
return View(data);
}
public ActionResult BuyItem()
{
PushIntoQueue();
ViewBag.DataBuyCount = data.ItemsToBuy.Count;
return PartialView("Partial1",data);
}
}
How to do that when i Click one of button just partial view render, now controller wants to move me to BuyItem view ;/
The first thing to do is to reference jQuery. Right now you have referenced only jquery.unobtrusive-ajax.min.js but this script has dependency on jQuery, so don't forget to include as well before it:
<script src="#Url.Content("~/Scripts/jquery.jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Now to your question: you should use submit buttons with an HTML form. In your example you don't have a form so it would be semantically more correct to use a normal button:
<input type="button" value="Buy" data-url="#Url.Action("BuyItem", "MsmqTest", new { area = "Msmq" })" />
<input type="button" value="Sell" data-url="#Url.Action("SellItem", "MsmqTest", new { area = "Msmq" })" />
and then in a separate javascript file AJAXify those buttons by subscribing to the .click() event:
$(function() {
$(':button').click(function() {
$.ajax({
url: $(this).data('url'),
type: 'GET',
cache: false,
success: function(result) {
$('#msmqpartial').html(result);
}
});
return false;
});
});
or if you want to rely on the Microsoft unobtrusive framework you could use AJAX actionlinks:
#Ajax.ActionLink("Buy", "BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
#Ajax.ActionLink("Sell", "SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" })
and if you want buttons instead of anchors you could use AJAX forms:
#using (Ajax.BeginForm("BuyItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Buy</button>
}
#using (Ajax.BeginForm("SellItem", "MsmqTest", new { area = "Msmq" }, new AjaxOptions { UpdateTargetId = "msmqpartial" }))
{
<button type="submit">Sell</button>
}
From what I can see you have already included the jquery.unobtrusive-ajax.min.js script to your page and this should work.
Maybe not the solution you were looking for but, I would forget about partials and use Javascript to call the server to get the data required and then return the data to the client as JSON and use it to render the results to the page asynchronously.
The JavaScript function;
var MyName = (function () {
//PRIVATE FUNCTIONS
var renderHtml = function(data){
$.map(data, function (item) {
$("<td>" + item.whateveritisyoureturn + "</td>").appendTo("#msmqpartial");
});
};
//PUBLIC FUNCTIONS
var getData = function(val){
// call the server method to get some results.
$.ajax({ type: "POST",
url: "/mycontroller/myjsonaction",
dataType: "json",
data: { prop: val },
success: function (data) {
renderHtml();
},
error: function () {
},
complete: function () {
}
});
};
//EXPOSED PROPERTIES AND FUNCTIONS
return {
GetData : getData
};
})();
And on the Server....
public JsonResult myjsonaction(string prop)
{
var JsonResult;
// do whatever you need to do
return Json(JsonResult);
}
hope this helps....

Trying to deal XML with Ajax

I Wrote a code that takes a generates XML file from Harvard Uni, and put it in a dropdown, next you can choose a course from the list and it will generates a table with the course details.
<script type="text/javascript" src="Script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$('#button').click(function () {
document.getElementById("span").style.visibility = "visible";
document.getElementById("button").style.visibility = "hidden";
$.ajax({
type: "GET",
url: "Harvard.aspx?field=COMPSCI",
success: function (data) {
var courses = data.documentElement.getElementsByTagName("Course");
var options = document.createElement("select");
$(options).change(function () {
ShowCourseDetails(this);
});
for (var i = 0; i < courses.length; i++) {
var option = document.createElement("option");
option.value = $(courses[i]).find("cat_num").text();
option.text = $(courses[i]).find("title").text();
options.add(option, null);
}
document.getElementById("selectDiv").appendChild(options);
document.getElementById("span").style.visibility = "hidden";
}
});
});
function ShowCourseDetails(event) {
// get the index of the selected option
var idx = event.selectedIndex;
// get the value of the selected option
var cat_num = event.options[idx].value;
$.ajax({
type: "GET",
url: "http://courses.cs50.net/api/1.0/courses?output=xml&&cat_num=" + cat_num,
success: function (data) {
$("#TableDiv").html(ConvertToTable(data.documentElement));
}
});
}
function ConvertToTable(targetNode) {
targetNode = targetNode.childNodes[0];
// first we need to create headers
var columnCount = 2;
var rowCount = targetNode.childNodes.length
// name for the table
var myTable = document.createElement("table");
for (var i = 0; i < rowCount; i++) {
var newRow = myTable.insertRow();
var firstCell = newRow.insertCell();
firstCell.innerHTML = targetNode.childNodes[i].nodeName;
var secondCell = newRow.insertCell();
secondCell.innerHTML = targetNode.childNodes[i].text;
}
// i prefer to send it as string instead of a table object
return myTable.outerHTML;
}
</script>
and the body:
<div id="main">
<div class="left">
<input id="button" type="button" value="Get all science courses from HARVARD"/>
<br />
<span id="span" style="visibility: hidden">Downloading courses from harvard....</span>
<div id="selectDiv"></div>
<div id="TableDiv"></div>
</div>
</div>
and What I get in the dropdown is only "undefined" on all the rows in the dropdown, can someone can see the problem with the code I wrote?
10x alot in advance :)
Working jsFiddle: http://jsfiddle.net/3kXZh/44/
Well, I found a couple of issues..
First, I'd stay away from setting "onclick" in the HTML. You want to separate your action layer from your content layer.
Since you're using jQuery anyway, try this:
$('#button').click(function() {
/* function loadXMLDoc contents should go here */
});
And change:
<input id="button" type="button" onclick="loadXMLDoc()" value="Get all sci..."/>
To:
<input id="button" type="button" value="Get all sci..." />
To solve your immediate problem in the JavaScript, change the loadXMLDoc function from this:
option.value = courses[i].getElementsByTagName("cat_num")[0].text;
option.text = courses[i].getElementsByTagName("title")[0].text;
to this:
option.value = $(courses[i]).find("cat_num").text();
option.text = $(courses[i]).find("title").text();
That should be enough to get you on to creating your tables from there.

worldpay integration asp.net

Hi I am trying to integrate worldpay on my asp.net website.
I have used this code to achieve the integration.
//test environment url
string url = "https://secure-test.worldpay.com/wcc/purchase";
//get all form elements
NameValueCollection formData = new NameValueCollection();
formData["testMode"] = "100";
//all the form fields here
//make the call to submit form data
WebClient webClient = new WebClient();
byte[] responseBytes = webClient.UploadValues(url, "POST", formData);
string response = Encoding.UTF8.GetString(responseBytes);
inputdiv.Visible = false;
outputdiv.Visible = true;
outputdiv.InnerHtml = response;
Basically I am getting the response and displaying it on a div. Everything works, but the links are having relative path which shouldn't be the case. Except the image urls, all other urls should point to worldpay. how to achieve this?
Any suggestion will be much appreciated.
Please try this, hope this would help a lot.
Html
<form action="/complete" id="paymentForm" method="post">
<span id="paymentErrors"></span>
<div class="form-row">
<label>Name on Card</label>
<input data-worldpay="name" name="name" type="text" />
</div>
<div class="form-row">
<label>Card Number</label>
<input data-worldpay="number" size="20" type="text" />
</div>
<div class="form-row">
<label>CVC</label>
<input data-worldpay="cvc" size="4" type="text" />
</div>
<div class="form-row">
<label>Expiration (MM/YYYY)</label>
<input data-worldpay="exp-month" size="2" type="text" />
<label> / </label>
<input data-worldpay="exp-year" size="4" type="text" />
</div>
<input type="submit" value="Place Order" />
</form>
SCRIPT
<script src="https://cdn.worldpay.com/v1/worldpay.js"></script>
<script type="text/javascript">
var form = document.getElementById('paymentForm');
Worldpay.useOwnForm({
'clientKey': 'Your_Client_Key',
'form': form,
'reusable': false,
'callback': function (status, response) {
document.getElementById('paymentErrors').innerHTML = '';
if (response.error) {
Worldpay.handleError(form, document.getElementById('paymentErrors'), response.error);
} else {
var token = response.token;
Worldpay.formBuilder(form, 'input', 'hidden', 'token', token);
console.log(token);
$.ajax({
url: "/Home/payment/",
data: { token: token },
success: function (data) {
},
dataType: "html",
type: "POST",
cache: false,
error: function () {
//Error Message
}
});
form.submit();
}
}
});
</script>
Serve Side Code C#
public ActionResult payment(string token)
{
var restClient = new WorldpayRestClient("https://api.worldpay.com/v1", "Your_Service_Key");
var orderRequest = new OrderRequest()
{
token = token,
amount = 500,
currencyCode = CurrencyCode.GBP.ToString(),
name = "test name",
orderDescription = "Order description",
customerOrderCode = "Order code"
};
var address = new Address()
{
address1 = "123 House Road",
address2 = "A village",
city = "London",
countryCode = CountryCode.GB,
postalCode = "EC1 1AA"
};
orderRequest.billingAddress = address;
try
{
OrderResponse orderResponse = restClient.GetOrderService().Create(orderRequest);
Console.WriteLine("Order code: " + orderResponse.orderCode);
}
catch (WorldpayException e)
{
Console.WriteLine("Error code:" + e.apiError.customCode);
Console.WriteLine("Error description: " + e.apiError.description);
Console.WriteLine("Error message: " + e.apiError.message);
}
return Json(null, JsonRequestBehavior.AllowGet);
}

Resources