AngularJS .Net WebAPI Upload image and save to database (MSSQL) - c#

I'm trying to upload an Image(can be bind to a model with a data type byte[]) from UI and save it in the database.
I'm using AngularJS connecting it to .NET WebAPI and saving it to MSSSQL Server
I cant find a good example using these technologies.
Question:
What approach is better to use? like ng-upload, FormData, ArrayBuffer, convert image to byte, etc. and how will you catch it from WebAPI?
Thanks!

I'm working on this feature these days. I share my experience (obviously it can be improved).
The key components I use are:
angular-file-upload
.NET ImageResizer: for resizing original image for thumbnails (excellent work by Nathanael Jones)
the stack is:
Angular.js Image Uploader
As I said, I use angular-file-uploader. There's no so much to add to the official documentation, but my uploader configuration is:
$scope.uploader = $fileUploader.create({
scope: $scope,
url: DisciturSettings.apiUrl + 'User/Image',
queueLimit: 1,
formData: [{ UserId: AuthService.user.userid }],
headers: AuthService.getTokenHeader()
});
In order to send the user id to the http request and to grant the access to the authorized route
WebApi 2 Action
The service does the main work. Here is the code.
As you can see, in this phase, I do two resizings of the image passed (one for the user profile picture and the other for user thumbnail picture). Besides this, I convert the byte[] in string and prepare the string for next retrievals. Doing this I prepend this part "data:image/gif;base64,", so, in the next entity readings (through EntityFramework) I don't have to manipulate the result anymore and I can put them directly in angular template:
<img ng-src="{{local.user.image}}" />
Obviously It can be made differently, but that's my case.
Database
At the moment I simply use nvarchar for storing images.
It's my first try so it can be improved for sure (if you have hints, don't hesitate).

Related

What is the best way to implement several concurrent Ajax request in one view/page?

In a data-driven web application, I have several razor views which contain tables that were created using tabulator, and are updated using self calling ajax functions on an interval. In most of the views, the number of tables is no more than three, and network performance and lag between updates is fairly quick. I am currently creating a view that houses over six tables, and am seeing an uptick in dropped request, stagnation in the data, and general slowness that seems to be directly attributable to the increased number of concurrent requests on the page. I am by no means a JavaScript or MVC expert, and am trying to investigate whether my code is just inefficient, or if the approach itself is wrong.
Essentially, each tabulator table has an ajax function that will hit an endpoint at the MVC layers, which routes to a WebApi2 endpoint to retrieve the latest data, and finally, use one of tabulators loading functions to load the data into the table. The data end is SQL using Entity Framework. I have tried several implementations built around this process, but below is the approach I am currently using.
// Function for waiting in between calls
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Function for getting data from endpoint
async function fetch() {
$.ajax({
type: "GET",
url: www.mydata.com,
}).done(async function (data) {
// Tabulator function for replacing existing data with new
table.replaceData(data);
await sleep(10000);
fetch();
}).fail(async function () {
await sleep(10000);
fetch();
})
}
// Call the fetch function the first time, self calls afterwards
fetch();
Each table in the view runs a version of the code snippet above. I added the sleep functions, hoping to introduce some delay between request. It is also worth pointing out that at the ASP.NET MVC layer, there is also increased congestion. It takes longer to service request made by the user to create a new entity, due to the all the other request flying back and forth.
To Spread out the request to the server you could choose to change the way your tables are configured.
Im assuming at the moment you are using the ajaxURL property to set the tables url, which will cause the table to make the request on load.
var table = new Tabulator("#example-table", {
ajaxURL:"http://www.getmydata.com/now", //ajax URL
});
This would result in all six tables making the request at the same time.
There are a couple of different approaches you could take
Delay Requests
You could instead leave this field out of your table definition (causing it to have an empty table on load, and then load the data later using the setData function. You could wrap this in a setTimeout function:
//wait one second before loading data
setTimeout(function(){
table.setData("http://www.getmydata.com/now");
}, 1000);
If you set each table with a different time out they will load in a staggered fashion.
Bundle Requests
Instead of allowing the tables to retrieve their data, you could retrieve it yourself in a single ajax request to the server that retrieve all the data, and then bundle it out to the tables using the setData function.
Although if you are loading significant amounts of data this could cause you delays.
Progressive Loading
If you are trying to transfer large amounts of data, this would certainly slow down the requests.
In these cases using the ajaxProgressiveLoad functionality of tabulator allows you to paginate your data and send it to the table in smaller chunks one after the other, which wont tie up your server continuously for so long:
var table = new Tabulator("#example-table", {
ajaxURL:"http://www.getmydata.com/now", //ajax URL
ajaxProgressiveLoad:"load", //sequentially load all data into the table
});
More details on this option can be found in the Progressive Ajax Loading Documentation

How to send data to another page except query string in Web-Farm

I have a webFarm application and an HTML image control as follows
<img id="logo" runat="server" src="" width="200" height="300" />
I am setting scr of this image from code behind as follows-
string mapId = "1234"; // mapId can vary
logo.Src = "./logo.aspx?mapId=" + mapId ;
Here logo.aspx is simple aspx page with following Page_load code-
logo.aspx
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "image/jpeg";
int mapIdValue= int.Parse(Request.Params["mapId"]); // mapId from querystring
string data = someFunction(mapIdValue); // to get image in Base64 String format
Response.BinaryWrite(Convert.FromBase64String(data));
Response.End();
}
This works fine.
My problem is, I dont want to send mapId in query string as it is exposed to user. So what would be the possible ways to send mapId from my page to logo.aspx.
I cant use session or HttpContext Items Collection as it is a Webfarm.
I tried using previousPage but not working for me..
Any ideas on this?
As the browser will retrieve the image in a subsequent, independent request, the server needs to be able to recognize the map id in this new request. It is not generally impossible to use sessions in a web farm, but it requires some kind of state server/database that all the servers in the farm share.
If you are unable to use sessions in your web farm, you need to transmit some information to the client that is used in the new request to identity the map. Independent of the way you choose, the client gets hold of some id information. Even though you do not want to use a query parameter, I'd still prefer using query parameters as opposed for instance using a cookie to hand over the id to the client. The main reason is that it will also work if you have several maps on a page.
In order to hide the real id for the client you can create an artificial id, e.g. a GUID that you can use to retrieve the image. You'd need to store the artificial id so that you can identify the map.
You can limit the artificial id so that it is valid only for some time, a number of requests or for a specific user. This way, the client is only able to use the artificial id in a very limited amount of time.
Of course, this requires some effort, but should be a stable way also in a Webfarm.
it may be usefull. please refer the below link
http://www.c-sharpcorner.com/UploadFile/gopenath/Page107182007032219AM/Page1.aspx

how to do API calls of Kentico using ASP.NET MVC?

I'm struggling with API calls of Kentico forms using ASP.NET MVC, so that I can use AngularJS to display the return data (JSON format).
Specifically, my client is using Kentico on their server to create data using "Forms" on Kentico and I want to get the records stored in these forms via API calls using ASP.NET MVC. What I'm thinking is that in the general section of the "Forms", I see the "Form code name" showing that "Code name is a string identifier of the object that can be used by developers in API calls or URLs". But it seems to be there's no good example of it on internet. Keep trying to search it but no luck. I also tried to access data directly in SQL Server in which kentico stores the data. But the table's name that Kentico uses in SQL Server to store the data is different from the ones in "Forms" or "Custom tables" in Kentico.
Hope someone can show me how to do it and I really appreciate it. Thanks in advance.
There is a very good example in the official documentation of Kentico.
Please note that Forms have been renamed a few times in the past (they were called BizForms and On-Line forms) that's the reason why the code below references CMS.OnlineForms and uses BizFormInfoProvider. It might also very well be the reason why you didn't find any good example :)
The example below shows how to retrieve Form's definition (metadata), get all the data and iterate through it.
using CMS.OnlineForms;
using CMS.DataEngine;
using CMS.SiteProvider;
using CMS.Helpers;
...
// Gets the form info object for the 'ContactUs' form
BizFormInfo formObject = BizFormInfoProvider.GetBizFormInfo("ContactUs", SiteContext.CurrentSiteID);
// Gets the class name of the 'ContactUs' form
DataClassInfo formClass = DataClassInfoProvider.GetDataClassInfo(formObject.FormClassID);
string className = formClass.ClassName;
// Loads the form's data
ObjectQuery<BizFormItem> data = BizFormItemProvider.GetItems(className);
// Checks whether the form contains any records
if (!DataHelper.DataSourceIsEmpty(data))
{
// Loops through the form's data records
foreach (BizFormItem item in data)
{
string firstNameFieldValue = item.GetStringValue("FirstName", "");
string lastNameFieldValue = item.GetStringValue("LastName", "");
// Perform any required logic with the form field values
// Variable representing a custom value that you want to save into the form data
object customFieldValue;
// Programatically assigns and saves a value for the form record's 'CustomField' field
item.SetValue("CustomField", customFieldValue);
item.SubmitChanges(false);
}
}
UPDATE:
The example above assumes that you're using the API from within the running Kentico instance. If you want to use Kentico API (DLLs) from an external application please follow the steps I described in another answer.
You also asked about the site identifier (siteId or siteName params of the BizFormInfoProvider.GetBizFormInfo() method). They refer to the SiteInfo object in Kentico (DB table CMS_Site). You can find site name if you navigate to Site->Edit site->General->Site code name.
If you don't want to use Kentico DLLs there is another option - using Kentico REST endpoint.

How to Upload Multiple Files Along with Other Form Fields, ASP.NET MVC

So I have a single form on a page. There are several text input fields and such. Right now there is also a jQuery file upload control wherein you can select several files. The problem I have right now is that I'm requiring that the user upload the files first (using the jQuery control) and then I save those files in Session state until the regular form posts the rest of the form fields. Then I pull the previously uploaded files from Session and do what I need to do.
So basically to fill out the form requires two separate POST operations back to the server. The files, then the remaining form fields.
I'm thinking there must be a better way to let a user select his/her files yet not post anything until the user submits the main form to post all the other fields. I've read several posts on this site, but I can't find one that addresses this particular issue.
Any suggestions/assistance is greatly appreciated.
I believe you can do this using Uploadify. There are two options you'd want to look at. First, set auto to false to prevent selected files from immediately being loaded. Second, use the formdata option to send along your other form fields along with the payload.
You'd then call the upload method when the user submits the form, uploading each file in the queue and sending the form data all at once.
Server Side Part:
You'll probably be submitting the form to an ASPX file or ASHX handler. I prefer using an ASHX handler since they're more light-weight. Both will allow you access to the HttpContext or the HttpRequest object. First, you'll need to check context.Request.Files.Count to make sure files were posted:
if (context.Request.Files.Count > 0) // We have files uploaded
{
var file = context.Request.Files[0]; // First file, but there could be others
// You can call file.SaveAs() to save the file, or file.InputString to access a stream
}
Obtaining the other form fields should be just as easy:
var formfield = context.Request["MyFormField"]; // Some form field
You can also write results back to the client, such as a JSON encoded description of any resulting errors:
context.Response.Write(response); // Anything you write here gets passed in to onUploadSuccess
I think that should get you started anyway!

Display two pdf documents on form submit in separate windows/tabs

I have .NET MVC web application. On my page there is a form to choose what pdf docs to display. I want to open pdf files in a new window or tab. The user can choose to display one or two pdf files. My form posts the data to controller, but i dont know how to return two pdfs from my controller and display in separate window/tab.
Does anyone have an idea how this can be done?
You can let the model write the urls to the documents into a javascript code block
#if(model.ShowPDFs)
{
<script>
function ShowPDF()
{
window.open('#model.PdfUrl1');
#if(model.Open2Pdf)
{
window.open('#model.PdfUrl2');
}
}
// opens the document after 3 seconds after the page has loaded
setTimeOut("ShowPDF()", 3000);
</script>
}
I made something similar (but I build the pdf server-side using ReportViewer) in this way:
my form post data to the controller action (with ajax)
the controller action reads the posted data, query the database
accordingly to it, and decide how many pdfs I have to return;
the controller action saves in the session, with a different key for every pdf (determined by my logic), the data to pass to ReportViewer;
the controller action returns (to the callback of the ajax call) an array with all the key used to store data in the sessions;
client side, the js callback loop over the returned array and, for every item, call (it opens a link in a different tab) a different controller (whose only responsibility is to send pdf to the request) passing it, in the query string, the key for that pdf;
the PrintController read the data from the session (using the key received), build the report and send it in the response.
I think you could do something similar; I don't understand how your pdf are built (are they data-depending or pdf pre-existing on the server?), but you can save the pdf stream, or the pdf path in the session instead of the data like me.
Hope to help; if you think that my solution can work for you and you need some code I can try to extract some from my codebase (in my case there are other issues and I have to rewrite the code if you need it ...).

Categories