Execute MVC method from View without redirection - javascript

I'm writing a web application running in an Active Directory environment using MVC5.
I have an AdminController controller, routing to a View where I can add users to the db.
public class AdminController : Controller
{
// some initializing code
public ActionResult AggiungiUtente()
{
if (Request.IsAjaxRequest())
{
return PartialView();
}
else
{
return View();
}
}
[HttpPost]
public ViewResult AggiungiUtente(AggiungiUtenteViewModel viewModel)
{
if (ModelState.IsValid)
{
return View(viewModel);
}
else
{
return View();
}
}
}
Within this View I want to put a simple textbox with a button where the user can write an employee's ID or name and he's presented a modal form with the list of AD objects found, then I'll take it from there.
As of now I have the code for all the "pieces", especially the AD tree research method that returns a serialized JSON object that is currently a static method within the ViewModel:
public static string ElencoPersonaleJSON(string chiave)
{
List<ADQuery.Elemento> ElencoPersonale = ADQuery.RicercaGenerica(chiave);
return ElencoPersonale.ToJSON(); //extension method
}
but how can I make it work with the rest of the application? How can I call this method, or how can I call it without being redirected to another view?
Thanks,
Davide.

Related

Check user web3.eth.accounts[0] value inside asp.net mvc action

How can I make sure inside my MVC action that the passed parameter string address is currently equal to JS window.web3.eth.acccounts[0]?
public ActionResult myAction( string address)
{
if(address == // there should be check js window.web3.eth.acccounts[0])
{
// other code
}
}
You can send it as a parameter to your action like:
public ActionResult myAction(string address, string eth3Info)
{
if(address == eth3Info)
{
//do the work
}
}
but honestly this won't make much sense as both things are coming from client side and can be easily manipulated.
You should have some backend call to get the window.web3.eth.acccounts[0] information from source.

Getting parameters from query string

I am creating a web page using ASP.Net WebAPi, MVC and Knockout.
I have a normal MVC controller that loads the pages when I need them:
[Authorize]
public class AdminController : Controller
{
public ActionResult Clients()
{
return View();
}
public ActionResult ClientEdit(int? Id)
{
return View();
}
}
And once the page is loaded, my Knockout model takes care of the loading of the data. So, the 'Clients' controller simply loads a list of all clients. When on that screen, a user can click 'Edit' next to a client, and the page is navigated to the 'ClientEdit' controller, which takes an id.
So, my knockout click event looks like this in my knockout view model:
self.EditClick = function () {
if (this.ClientId && typeof this.ClientId !== 'undefined') {
window.location.href = "/Admin/ClientEdit/" + this.ClientId;
}
else
window.location.href = "/Admin/ClientEdit/";
}
(It handles the 'Create New' button and the edit button, hence the 'if')
Once I redirect, the MVC controller loads the page, and the URL is:
http://localhost:49389/Admin/ClientEdit/1
I then load the knockout model, and would like to make an API call to get the data...
After my page loads, I want to bind the view model to the page. Here's my view model at the moment:
function AdminClientEditor() {
var self = this;
self.Name = ko.observable("");
self.ContactName = ko.observable("");
ko.applyBindings(new AdminClientEditor(), $("#clienteditor")[0]);
So, I will create a $.get method that calls a webAPI method that will return me data based on the id. I just need to get the ID somehow.
But, how do I get the Id (In this case, '1', from the URL?
And, is this the right way to achieve what I am trying to do?
You can pass the id value to view via viewbag.
public ActionResult ClientEdit(int? Id)
{
ViewBag.ClientId=id;
return View();
}
and in the view's script section
var clientId="#ViewBag.ClientId";
alert(clientId);
// use this
If your javascript code which accesses this id value is inside a separate external js file, you may set this value to a js variable in your view and access it in your js file. Make sure to use namespacing to avoid global variable overwriting value issues.
So in your view
<script>
var myApp = myApp || {};
myApp.ClientId= "#ViewBag.ClientId";
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
And in the PageSpecificExternalJsFile.js file,
var clientId=myApp.ClientId;
//use this as needed
I'm not sure if this is the best way, but you can get the ID from the URL by using JS:
var id = GetID();
function GetID() {
var href = location.href;
var results = href.split("/");
return results[results.length - 1];
}
I've come up with this solution which works, but I am unsure if it's the best way. It seems pretty good.
I created a MVC ViewModel class in my application code, called 'GenericParameteModel', which at the moment, has a single parameter, "Id".
I then modified my page loading MVC method:
public ActionResult ClientEdit(int? Id)
{
var mv = new GenericParameteModel { Id = Id };
return View(mv);
}
On my View page, I added the model 'GenericParameteModel' to the View.
I created a hidden field, called 'ClientId' on the view.
<input type="hidden" id="clientId" value="#model.Id">
Then, within my knockout view model, I check if $("#clientId").val() has a value. If so, I do the $.get call, using that value, and populate my view model.
In doing so, all my initial page loads from MVC will have the ability to you the GenericParameteModel, and it will be a pattern for other pages. As it's a model, I can add new fields as my application requires.
This seems to work well. I'm unsure if this is an acceptable way as I am new to this (MVC to load views and the Knockout/WebApi to get the data after loading). But it seems neat and manageable.

Pass HTML code trough Ajax Asp.Net MVC

I'm trying pass a html code trough Ajax like this:
Using plugin 'summernote' (WYSIWYG Editor)
var description = $('#ticketDescription').code();
This give me for example:
<span style="font-weight: bold;">asdasdasd<span>sadasd
and when Ajax process this give an 500 internal error
$.ajax({
url: '/Ticket/NewTicket',
type: 'POST',
data: {
companyId: companyId,
subject: subject,
ticketDescription: description
},
success: function(result) {
....
},
error: function(result) {
}
});
The problem is solved by removing the '<' character from string.
Any solution to this?
Thanks
Edit: The only way I found so far is:
In javascript:
description = escape(description);
and in the controller:
ticketDescription = HttpUtility.UrlDecode(ticketDescription);
Is it correct?
ValidateInput and AllowHtml attribute is what you need to set in the property
By default Asp.Net MVC doesn't allow a user to submit html for avoiding Cross Site Scripting attack to your application.
ValidateInput Attribute
This is the simple way to allow the submission of HTML. This attribute can enable or disable input validation at the controller level or at any action method.
ValidateInput at Controller Level
[ValidateInput(false)]
public class HomeController : Controller
{
public ActionResult AddArticle()
{
return View();
}
[HttpPost]
public ActionResult AddArticle(BlogModel blog)
{
if (ModelState.IsValid)
{
}
return View();
}
}
Now, the user can submit Html for this Controller successfully.
ValidateInput at Action Method Level
public class HomeController : Controller
{
public ActionResult AddArticle()
{
return View();
}
[ValidateInput(false)]
[HttpPost]
public ActionResult AddArticle(BlogModel blog)
{
if (ModelState.IsValid)
{
}
return View();
}
}
Now, the user can submit Html for this action method successfully.
Limitation of ValidateInput attribute
This attribute also has the issue since this allow the Html input for all the properties and that is unsafe. Since you have enable Html input for only one-two properties then how to do this. To allow Html input for a single property, you should use AllowHtml attribute.
AllowHtml Attribute
This is the best way to allow the submission of HTML for a particular property. This attribute will be added to the property of a model to bypass input validation for that property only. This explicit declaration is more secure than the ValidateInput attribute.
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
public class BlogModel
{
[Required]
[Display(Name = "Title")]
public string Title { get; set; }
[AllowHtml]
[Required]
[Display(Name = "Description")]
public string Description{ get; set; }
}
Make sure, you have removed the ValidateInput attribute from Conroller or Action method. Now, the user can submit Html only for the Description property successfully.

How to control function called by this.form.submit in mvc

I am using Telerik.MVC extensions and certain controls to not pass data to the controller on events.
Tee dropdown must call this.form.submit during an OnChange event to register that the user made a selection.
function ddl_OnChange(e)
{
this.form.submit();
}
In the controller I have:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind()] ViewModel.Designer model, string ddlDatabase,
string ddl, string cboTemplate, string command)
{
if (ModelState.IsValid)
{.....
On the OnChange, the value of the ddl control is passed through the ddl value.
My problem is, I have multiple dropdown and combos and would like to control the action taken by the controller depending on the choice made. How can I direct the this.form.submit();
to other functions. Also, how can I pass data additional data back to this other method.
Solution:
In the script, set the action property:
function ddlTable_OnChange(e)
{
this.form.action += '\\ddlTable_OnChange';
this.form.submit();
}
In the controller, create matching function:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ddlTable_OnChange([Bind()] ViewModel.Designer model, string ddlDatabase,
string ddlTable, string cboTemplate, string command)
{
return Index();
}

Custom action result return specific view in MVC C#

I have an MVC application which i am trying to give the user the opportunity to download a zip of files,but unsuccesfully.Let me explain further.
Inside my view(ImageViewer.cshtml) i have a div class with an on click event that when pressed i call the controller method(ImageViewerController.GetZipPhotos) which handles the download of the zip file.See below:
div class="text" onclick="GetZipPhotos()">Download</div>
and the Javascript that get called is this:
function GetZipPhotos() {
$.ajax({
url: '#Url.Action("GetZipPhotos", "ImageViewer",Request.Url.Scheme)',
type: 'POST',
contentType: 'application/zip',
error: function () {
alert('There was an error!'+result);
}
});
}
Now, inside my ImageViewerController i have the following method:
[HttpPost]
public ActionResult GetZipPhotos()
{
ZipResult newZipResult=new ZipResult(
Server.MapPath("~/File1.txt"),
Server.MapPath("~/File2.txt")
);
newZipResult.OutPutZipFileName = "PhotosZip.zip";
return newZipResult;
}
and the declaration of the ZipResult custom action is:
public class ZipResult:ActionResult
{
private IEnumerable<string> _filesToZip;
private string _outPutZipFileName="ZipFile.zip";
public ZipResult(params string[] filesToZip)
{
this._filesToZip = filesToZip;
}
public override void ExecuteResult(ControllerContext context)
{
using (ZipFile oneZipFile = new ZipFile()) {
oneZipFile.AddFiles(_filesToZip);
context.HttpContext.Response.ContentType = "application/zip";
context.HttpContext.Response.AppendHeader("content-disposition", "attachment; filename=" + _outPutZipFileName);
oneZipFile.Save(context.HttpContext.Response.OutputStream);
}
}
}
The problem is that the code ofcourse doesn't work because the name of the view that called the controller is different from the actual method(GetZipPhotos).The view's name is ImageViewer.cshtml and the controller's name is ImageViewerController.
As fas as i have understood, the MVC framework uses code conventions, so it expects the name of the method to be the same as the view.The problem is that my view and the method are diferrent so the response never gets to back to the view.
I thought of creating a new view that has basically nothing inside, just to call it from the method and return the zip file.If this could be a possible solution, how can i tell from the action result which view to send the response?
No need to use ajax for the file download. The browser will normally start the download and keep you on the same page. Also, no need for a custom action result, you can just use FileResult. Try something like this:
public FileResult GetZipPhotos()
{
var filesToZip = new List<string> { Server.MapPath("~/File1.txt"), Server.MapPath("~/File2.txt") };
var oneZipFile = new ZipFile();
oneZipFile.AddFiles(filesToZip);
return File(oneZipFile.ToByteArray(), "application/zip", "PhotosZip.zip");
}
Of course, you'll need to figure out this part oneZipFile.ToByteArray(), but the ZipFile class probably already has something like that.
Your ajax call is redirecting the response into nowhere.
I would do it like this:
use a hidden iframe, change its src to the desired path in your function and it should be prompting a file dialog.

Categories

Resources