How to pass antiforgery token when calling using ajax load method - ajax

I have an application, where if I add the [ValidateAntiForgeryToken] to the controllers post method, it fails with Exception message: The required anti-forgery form field "__RequestVerificationToken" is not present.
The method that posts to the server is triggered using the ajax LOAD method. Does anyone know how I can pass the anti forgery token to this call?
Here's a code snippit which used the ajax load method.
if ($("#" + sectionId + "div")[0].style.display == "none") {
$("#" + sectionId + "div")[0].style.display = "";
$("#" + sectionId + "img").attr("src", "Content/Images/uparrow.gif");
$("#" + sectionId + "div").load(
"getSubjectDetails/" + sectionId + "/" + $("#subjectdetails option:selected").val(),
{ dataKeys: $("#mykey").html() + "," + $("#countryDiv").html() });
e.preventDefault();
}

Related

Unable to send string to a controller method via ajax

I'm implementing asp.net core 3.1. I want to send a "year" value as the input parameter of my method controller. when I debug my project I can see that "year" has a value in ajax call but the argument of year in the controller method is null. I appreciate if anyone can suggest me to solve the issue.
Here is the related code in razor view:
$('#exampleModal').modal('#ViewBag.ModalState');
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var year = $("input[name='Year']:checked").val();
console.log('myyear:' + year);
//My problem is here, when sending year value to the
//ProductDetails method
$.get('#Url.Action("ProductDetails", "Home")/' + {year: year}, function (data) {
$.each(data, function (index, value) {
var markup = "<tr><td>" + value.apName +"</td></tr>";
$("#classTable").append(markup);
})
});
});
Home controller method:
public IList<ApiApplicantDTO> ProductDetails(string year)
{
Console.WriteLine("year:" + year);
}
Be sure the year has value.And your url is incorrect,you need to change like below:
var year = "2019";
$.get('#Url.Action("ProductDetails", "Home")?year=' + year, function (data) {
//...
});
Result:

How to display images in .cshtml page from Private Azure Storage in MVC?

I'm getting following error on inspecting the html page:
<Error>
<Code>AuthorizationFailure</Code>
<Message>This request is not authorized to perform this operation.
RequestId:7b853423-101e-0015-51e5-905acd000000
Time:2020-09-22T13:38:05.2479851Z
</Message>
</Error>
I have created key for Azure connectionstring in web.config file, written method for accessing azure storage blob making private to public:
public ActionResult BlobManager(string ContainerName = "images")
{
string ConnectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"].ToString();
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
blobContainer = cloudBlobClient.GetContainerReference(ContainerName);
//Make available to everyone
blobContainer.SetPermissions(new BlobContainerPermissions{
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
This is my controller method:
[HttpGet]
public JsonResult GetImageList(int TaskID)
{
var data = (from d in _context.ImgTable
where (d.Taskid == TaskID )
select new
{
d.ImageID,
d.Taskid,
d.ImagePath,
}).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
Please help out how to go further. I want to display images in in html page.
I'm selecting Taskid from dropdownlist and on-click of it display related images to that taskid in html table.Below is the js function:
$.ajax({
type: 'GET',
url: '#Url.Action("GetImageList")',
datatype: JSON,
data: {
'TaskID': $("#tasklist").val() //getting selected TaskID from dropdown
},
success: function (data) {
var row_no = 1;
$.each(data, function (i, item) {
var path = "https://abcdatastorage.blob.core.windows.net/task/"; //azure storage url
var img = item.ImagePath; //getting imagepath from local db
img = img.replace(/\s+/g, '%20');
var img1 = img.split('\\');
img = (path + img1[5]); //joining above url to get complete url to bind with <img src>
+ "<td id='ItemId" + row_no + "' >" + item.ID + "</td>" // displaying image id in html table
"<td>"
+ "<div><img id='Image" + row_no + "' src=" + img + " class='img-fluid img-thumbnail' alt='' style='width:500px; height:350px;' />" // display image for that imageid
+ "</div></td > "
});
Can i pass directly the azure storage url in html? Can i access and dispaly images?
If the azure storage is private, how the images will get display?
Below is the src i'm getting thru concatenating url as above written in js. But image is not seen.
<div>
<img src='https://abcimages.blob.core.windows.net/images/418;1488163937486;d%20V%20Phase%205.0%20kV.jpg' class='img-fluid img-thumbnail' alt='' style='width:500px; height:350px;' />
</div>
Please help out with the solution. How can i access private azure storage through code and the images can be displyed.
I have a simple way to implement this function, and your code does not need to be modified a lot.
My suggestion is that you write a general GetAccountSASToken method. If you need security verification, it is recommended to call this method after passing the verification, so that the generated sas token can be generated and appended to the img URL.
You can read offical document Create an account SAS with .NET.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.WriteLine(GetAccountSASToken());
}
public static string GetAccountSASToken()
{
// To create the account SAS, you need to use Shared Key credentials. Modify for your account.
const string ConnectionString = "DefaultEndpointsProtocol=**fix=core.windows.net";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
// Create a new access policy for the account.
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Read | SharedAccessAccountPermissions.Write | SharedAccessAccountPermissions.List,
Services = SharedAccessAccountServices.Blob | SharedAccessAccountServices.File,
ResourceTypes = SharedAccessAccountResourceTypes.Service | SharedAccessAccountResourceTypes.Container | SharedAccessAccountResourceTypes.Object,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Protocols = SharedAccessProtocol.HttpsOnly
};
// Return the SAS token.
return storageAccount.GetSharedAccessSignature(policy);
}

How to add a new method to a controller in asp.net webAPI 2

I'm using this tutorial on www.asp.net to learn about .net web api 2. I added a second lookup on the index page:
<div>
<h2>Search by Category</h2>
<input type="text" id="catId" size="5" />
<input type="button" value="Search" onclick="findCat();" />
<p id="categories" />
</div>
and modified the existing javascript to add a lookup for category. The idea being to enter a category (eg, Toys) and the API would return the products in that category:
function findCat() {
var uri = 'api/GetCategory';
var cid = $('#catId').val();
$.getJSON(uri + '/' + cid)
.done(function (data) {
$('#categories').text(formatItem(data));
})
.fail(function (jqXHR, textStatus, err) {
$('#categories').text('Error: ' + err);
});
}
I added a method in the controller class that (I thought) would handle this:
public IHttpActionResult GetCategory(string Category)
{
var product = products.FirstOrDefault((c) => c.Category == Category);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
When I run a search on category it is unable to find the products in that category. What am I missing (besides about 6 months of study! I know!)
Thank you
By reading your comments you tell us that you only have the defaultApi in the route configuration, that would be:
api/{controller}/{id}
You also tell us that you get a NotFound error, I guess that this happens because it cannot find the controller/method.
By reading your script you are actually doing this:
function findCat() { //actual request URL:
var uri = 'api/GetCategory'; //api/GetCategory/
var cid = $('#catId').val();
$.getJSON(uri + '/' + cid) //api/GetCategory/1
You use GetCategory as controller, which is not correct, your controller is the class name + Controller. So in your case probably ProductController
Secondly, WebApi doesn't look for method names, it only looks for a distinction in HTTP-request type and parameters. So if you have two methods with different names but they are both a GET request-type and both have a int as parameter, Web Api doesn't know which one to use.
Your api link should be: api/Product?category="blabla"
What you can do is add additional routing to a method, the default AccountController gives good examples for this.
In your case:
[RoutePrefix("api/Product")] //you have to specify this if you would like to do custom routing.
public class ProductController : ApiController
{
//GET: api/Product/Category?category="blabla"
[HttpGet]
[Route("Category")] //route constraint
public IHttpActionResult GetCategory(string category)
{
var product = products.FirstOrDefault((c) => c.Category == Category);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
So now you can update your script, your script is made for getting something by Id, while you want this to be by string, you can probably figure it out. Something like this I guess (not that good with javascript yet.
function findCat() {
var uri = 'api/Product/Category';
var cid = $('#catName').valueOf();
$.getJSON(uri + '?category=' + cid)
.done(function (data) {
$('#categories').text(formatItem(data));
})
.fail(function (jqXHR, textStatus, err) {
$('#categories').text('Error: ' + err);
});
}
Optional: If you like to have you link like this: api/Product/Category/blabla you have to add this:
[Route("Category/{category}")]
Web API Routing: article
Attribute routing and constraints: article

signalR maintaining user connection ids

I am trying to maintain a connection id for the user ,i mean even he refreshes the page he gets the same connectionid
This is what i could do till now
the javascript part
// Start the connection
$.connection.hub.start(function () { chat.join(projectId, userId, userName); }).done(function () {
alert("Connected!");
var myClientId = $.connection.hub.id;
setCookie("srConnectionid", myClientId, 1);
});
function setCookie(cName, value, exdays) {
try{
var exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate);
document.cookie = cName + "=" + c_value;
}
catch(err){
alert(err.Description);
}
}
and then i made a class that inherits IConnectionIdFactory like this
public class MyConnectionFactory : IConnectionIdFactory
{
public string CreateConnectionId(IRequest request)
{
if (request.Cookies["srconnectionid"] != null)
{
return request.Cookies["srconnectionid"];
}
return Guid.NewGuid().ToString();
}
}
i registerd the above class in Application_start() as below
protected void Application_Start()
{
AspNetHost.DependencyResolver.Register(typeof(IConnectionIdFactory), () => new MyConnectionFactory());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
My problem is everytime MyConnectionFactory class is called inside the CreateConnectionId
request.Cookies["srconnectionid"] is null everytime,so the user is assigned new connectionid everytime.I could find only one link that helped me to maintain connection ids.It is http://www.kevgriffin.com/maintaining-signalr-connectionids-across-page-instances
Can any one suggest how to fix my problem or is there any other approach to reuse the connection id for the same user...?
The Cookie value is set in the clientside.I have been trying this for 2 days.It would be great help
Thanks in advance
The expire date for the cookie should be UTC string (you are not doing this, so most probably the server is treating your cookie as expired). Change your code like this:
var cValue = escape(value) + ((exdays==null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = cName + "=" + cValue;
Or you might just use jQuery Cookie plugin for setting the cookie.
UPDATE
Also the name of cookie is inconsitent in the code you have provided. You are setting the cookie with name 'userConnectionid' but trying to access by name 'srconnectionid'. Please check if you haven't made a spelling error there.
Make sure you set the cookie's path, especially if the page is sitting in a subdirectory. I'm following a similar approach, and when the cookie path is set to root, then it all works.

IE9 and AJAX - List Not Refreshing (ASP.NET and MVC3)

Im new to Web Development and its principles so apologies if my question does not seem clear.
Story So Far......
Im writing an Open Source application to learn ASP.NET MVC3. Now im at the stage where im creating my CRUD controller to allow me to create some new Types. Now I have created a SiteAdmin Controller which holds my Dashboard, with has a View. The View will contain tabs . I have been learning how to handle tabs using the following blog post and JQuery UI
http://ericdotnet.wordpress.com/2009/03/17/jquery-ui-tabs-and-aspnet-mvc/
I have decided to use the AJAX example to handle my tabs, whereby I pass an index parameter to a Controller Action Method called AjaxGetTab . This method (as per the blog post) returns a Partial View for the required Type. Within the Partial View there are Create Controller Action Method's, for e.g. CreateTransactionType (HttpPost), which create new records.
"Stop the waffling what is the problem"
The problem is that my list within the tab on the view doesn't refresh after the Create method is finished. This problem only exists in IE9 (Only IE i have tested) but Chrome and Firefox work, i.e. the list refreshes.
I have checked the Database records exists.
My code is here:
JQuery in Dashboard.cshtml:
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs();
getContentTab (1);
});
function getContentTab(index) {
var url='#Url.Content("~/SiteAdmin/AjaxGetTab")/' + index;
var targetDiv = "#tabs-" + index;
var ajaxLoading = "<img id='ajax-loader' src='#Url.Content("~/Content")/ajax-loader.gif' align='left' height='28' width='28'>";
$(targetDiv).html("<p>" + ajaxLoading + " Loading...</p>");
$.get(url,null, function(result) {
$(targetDiv).html(result);
});
}
SiteAdminController AjaxGetTab Method:
/// <summary>
/// AJAX action method to obtain the correct Tab to use.
/// </summary>
/// <param name="index">Tab number</param>
/// <returns>Partial View</returns>
public ActionResult AjaxGetTab(int id)
{
string partialViewName = string.Empty;
object model = null;
//--Decide which view and model to pass back.
switch (id)
{
case 1:
partialViewName = "_TransactionType";
model = db.TransactionTypes.ToList();
break;
case 2:
partialViewName = "_DirectionType";
model = db.DirectionTypes.ToList();
break;
case 3:
partialViewName = "_UserType";
model = db.UserTypes.ToList();
break;
case 4:
partialViewName = "_CurrencyType";
model = db.CurrencyTypes.ToList();
break;
case 5:
partialViewName = "_tabError";
break;
}
return PartialView(partialViewName,model);
}
}
SiteAdminController CreateTransactionType Method:
[HttpPost]
public ActionResult CreateTransactionType(TransactionType model)
{
try
{
// TODO: Add insert logic here
if (ModelState.IsValid)
{
model.id = Guid.NewGuid();
model.RecordStatus = " ";
model.CreatedDate = DateTime.Now;
db.TransactionTypes.AddObject(model);
db.SaveChanges();
}
return RedirectToAction("Dashboard");
}
catch
{
return PartialView("_tabError");
}
}
Replace your
$.get(url,null, function(result) {
$(targetDiv).html(result);
});
By:
$.ajax({
type: 'get',
url: url,
cache: false,
success: function(result) {
$(targetDiv).html(result);
}
});
The problem is that IE caches ajax requests, so by setting cache: false in the settings it should work.

Resources