Good Practice mvc conditional button and its code - c#

I'm coding an MVC3 application with ajax and I got a situation.
I have to show na Button only if an condition is true. Ok its easy to do.
#if (Model.AAA == ENUM.AAA)
{
<button>OK</button>
}
but this button going to call an ajax function.
Now my doubt is, WHERE A PLACE MY AJAX CODE?
if I do this:
#if (Model.AAA == ENUM.AAA)
{
function OK(){
$.ajax({});
}
<button>OK</button>
}
it's sound ugly code!!!
It's seens that the code it' not in the right place but the ajax code is "safe", I mean, the ajax code will only exist if the button exist.
but if I place my code in head section, An advanced user will be able to call the ajax function.
or if a make an #if clause to enclose the script, I will duplicate code like this
<head type="text/javascript">
#if (Model.AAA == ENUM.AAA){
function OK(){
$.ajax({});
}
}
</head>
....
<body>
....
#if (Model.AAA == ENUM.AAA)
{
<button onclick="OK()">OK</button>
}
....
</body>
So, What is the best practice to face this situation, the best approach?

It sounds almost like you are wanting to use the presence/lack of a snippet of Javascript code to control access to a call on your server. Don't do that.
Your server should always be evaluating if the action can be called by the user in question at that moment. What if the user leaves the page open in their browser, and some application state change happens that would block the user from calling that action... but their browser is still displaying the button? Or if a clever user decides to play around with your URLs by poking around in the source?
I would recommend just putting the javascript in a common location and calling it from there, as that keeps all your Javascript together.

Just have the one conditional in your markup, like you have:
#if (Model.AAA == ENUM.AAA)
{
<button id="OkButton">OK</button>
}
Then tweak your Javascript slightly so you don't include Razor (that way it can be extracted into an external JS file):
<head type="text/javascript">
WireUpButton();
function WireUpButton() {
var okbutton = document.getElementById("OkButton");
if (okbutton) {
okbutton.onclick = OK;
}
}
function OK(){
$.ajax({});
}
</head>

The server should control the request call and check for the correct state. #Andrew Barber points this out, but that is not just leaving the browser open. But the advanced user could share the ajax request, with others that don't have permission, or use it maliciously
Trying to answer the question in a bit more depth, it could be not a simple script like this, but a file or some JS library, maybe you don't have control about the server you ajax is accessing. In that case, you'd probably want to duplicate the verification.

Related

Show a loading animation while function completes

I have a function inside my .aspx.cs code which takes wuite a long time to do the processing until when I want to display a cool loading animation. I looked some of the earlier posts but either these didn't work for me, or were having solution specific to Page loading scenario (not loading a while a function completes).
I guess the right approach would be to fire a Javascript startLoader() function just before the the main function starts (which takes a long time), and then call a stopLoader() from the .aspx.cs itself to stop the loader when the function ends. Any suggestions how to implement this?
Yes, I've done this in ASP.NET Web From (not a ASP.NET MVC solution). You need to provide OnSubmit client side event handler. It basically break down to three parts: Javascript, HTML Div, and one line code behind:
Javscript:
function ShowLoading(e) {
// var divBg = document.createElement('div');
var divBg = document.getElementById('blockScreen');
var divLoad = document.createElement('div');
var img = document.createElement('img');
img.src = 'images/ajax-loader.gif';
divLoad.setAttribute("class", "blockScreenLoader");
divLoad.appendChild(img);
divBg.appendChild(divLoad);
document.getElementById('blockScreen').style.display = 'block';
// These 2 lines cancel form submission, so only use if needed.
//window.event.cancelBubble= true;
//e.stopPropagation();
}
function HideLoading() {
//alert('hideloading');
document.getElementById("form1").onsubmit = null;
document.getElementById('blockScreen').style.display = 'none';
//alert('done');
}
Add following DIV
<div id="blockScreen" class="blockScreen" style="display:none"> </div>
Finally, add the following to Page_Load in code behind.
Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "submit", "ShowLoading()");
Now, all of your page postbacks are essentially have to call onsubmit event. It will display the animation before the page postback finishes.
if you really want to do, then the only way is webworkers. You've probably heard about them, or if not, i seriously recommend to have a look.
Yes, fire startLoader() on OnCliencClick of your button or whatever element you are using to fire the server-side event and call stopLoader() from the server-side at the end of your process. Something like this:
//rest of the server-side code above ...
Page.ClientScript.RegisterStartupScript(this.GetType(), "someKey", "stopLoader();", true);
If you don't mind that the browser is not responsive in the meantime, the simplest way of doing this is using an animated gif:
Activity indicators
ajaxload.info
webscriptlab
The trick is showing the image when starting your processing, and hiding it when finished. You can show it in an img, and use jQuery or whatever you want to show/hide it.
If you need the browser to keep responsive, use Web Workers. But be aware that some of the older browsers don't support it. See this reference

How to "PRE-PROCESS" ajax call before showing the mvc view?

I'm not so expert with ajax, so I find it hard to look for the better answer. I've tried creating separate ".js" file that contains the call for rest service (for validation of user session), but it doesn't work.
My goal is to validate user session before loading my views (in MVC). The only way to use the logic of validating the given session with the database is to call a rest service via url using ajax.
This code works well (inside Home View):
<script type="text/javascript">
$(function () {
$.get('#Url.Action("GetSession", "Auth")', function (getdata) {
if (getdata.UserID && getdata.SessionID && getdata.SourceIP) {
$.post('http://website.com/Rest/Authenticate/ValidateUserSession', JSON.stringify(getdata), function (response) {
if (response == false) { window.location.replace('#Url.Action("SignUp", "Auth")'); }
});
} else {
window.location.replace('#Url.Action("SignUp", "Auth")');
}
});
});
</script>
<h2>
Home</h2>
#*The content here should not appear, unless session is validated.*#
The only problem is that, the process of validation takes 3 to 5 seconds, so the user sees the Home page before the ajax call returns the result whether the validation was successful or not. If validation/response returns false it will redirect to sigup page.
I don't know what is the best practice with this process. For now I jsut don't want the Home view show to the user unless session is validated. Hope I'd explain it well. Please suggest if you have the better idea.
Additional info:
If possible, I like doing this:
<script type="text/javascript">
if(!validated()){
window.location.replace('#Url.Action("SignUp", "Auth")');
}
</script>
<h2>
Home</h2>
#*The content here should not appear, unless session is validated.*#
Why can't you consume the rest service at server side ? Technically there should be no reason for not being able to do that. Here's a tutorial discussing exactly that : http://codebetter.com/johnvpetersen/2012/03/22/accessing-a-asp-net-webapi-rest-service-from-asp-net-mvc/
That should take care of everything. If for some reason that's not possible for you, then you can do the following,
Make your home page a partial view.
Instead of loading home page, load an empty page with processing icon (or whatever message you want to show.)
Talk to the REST service and if got the reply then load Home page's partial view using JQuery else load sign up partial view.
Here's an article discussing how to load MVC partial views using JQuery: http://www.codeproject.com/Articles/34221/JQuery-Partial-Views-in-ASP-NET-MVC

Load a page with pagemethods inside a div tag inside a MasterPage

I have a MasterPage which will appear in every page in the application and I'm trying to load a "LoginBox" which uses PageMethods inside a Div tag in this MasterPage
So far I have tried doing as I would do on a Content Page, tried converting it into a User Control and tried using a server side include (< !--#include file="LoginBox.aspx"-->)
None succeeded.
I can see with firebug that the webresources get loaded but the PageMethods javascript isn't created in any of those methods.
I am REALLY trying to avoid having to create a WebService for this, and moving the LoginBox is not an option, I would rather drop the MasterPage idea, but then maintenance would become hell.
I need ideas or a direction on this.
Any help is appreciated
I got it working successfully with an iframe loaded from javascript, to me it's an ugly solution, but still one. I'm open for better solutions
<script type="text/javascript">
(function () {
var e = document.createElement('iframe');
e.setAttribute("src", "LoginBox.aspx");
e.setAttribute("scrolling", "no");
e.setAttribute("frameborder", "0");
e.setAttribute("height", "73px");
e.setAttribute("width", "225px");
e.setAttribute("marginheight", "0px");
e.setAttribute("marginwidth", "0px");
e.async = true;
document.getElementById('loginboxd').appendChild(e);
} ());
</script>
Looks to me like you're mashing classic asp with ASP.NET
the point of user controls is to encapsulate exactly what you are doing here.
even then however you will find your attempts to componentize your code will still lead to a messy mess mess. consider moving over to ASP.NET MVC if you can. with that you can do far more suitable and cleaner things to keep your codebase clean.

Why does it make a difference where I include the jQuery script file?

On my master page (for all pages in my site) I have a ToolkitScriptManager.
On my content page, there are a series of hyperlinks and divs for collapsible functionality.
The code to show/hide the panels work like the following:
$(document).ready(function() {
// Hookup event handlers and execute HTML DOM-related code
$('#nameHyperLink').click(function() {
var div = $('#nameDiv');
var link = $('#nameHyperLink');
if (div.css('display') == 'none') {
link.text('Hide Data');
div.show('100');
}
else {
link.text('Show Data');
div.hide('100');
}
});
});
If I include a ScriptReference to the jQuery 1.4.2 file in the toolkitscriptmanager, the javascript code is executed incorrectly on the page (only the text for the hyperlink is changed, the div is not actually shown.) However, if I don't include the jQuery file in the ToolkitScriptManager and instead include it in the content page, it works correctly.
I'm a Javascript/jQuery newbie, and this makes no sense at all. What's going on here?
Positioning of the script include is important for the jQuery ref. If you look at your generated source I would bet the tag is below the script function(). You should make sure that the jQuery reference comes as early as you can get it in the page source.
Try moving the jQuery library reference into the head of your master page, that should work. Otherwise post up some source!
Like Tj says... should probably be in the head section of your master page. Also, it's nice to link to Google's version of this library, because chances are your users will already have it cached. For instance, look at the source for this very page.
The two most probable causes here are $ not being defined yet (see Tj's answer) and $ getting defined by another library, such as prototype.
I would highly suggest you look into using Firebug's javascript debugger, or at least take a look at Firefox's built in error console (Tools -> Error console). That will give you a much better clue what is going on other than "it's not working."

Detect if a page is within a iframe - serverside

How can I detect server-side (c#, asp.net mvc) if the loaded page is within a iframe? Thanks
This is not possible, however.
<iframe src="mypage?iframe=yes"></iframe>
and then check serverside if the querystring contains iframe=yes
or with the Referer header send by the browser.
Use the following Code inside the form:
<asp:HiddenField ID="hfIsInIframe" runat="server" />
<script type="text/javascript">
var isInIFrame = (self != top);
$('#<%= hfIsInIframe.ClientID %>').val(isInIFrame);
</script>
Then you can check easily if it's an iFrame in the code-behind:
bool bIsInIFrame = (hfIsInIframe.Value == "true");
Tested and worked for me.
Edit: Please note that you require jQuery to run my code above. To run it without jQuery just use some code like the following (untested) code to set the value of the hidden field:
document.getElementById('<%= hfIsInIframe.ClientID %>').value = isInIFrame;
Edit 2: This only works when the page was loaded once. If someone have idea's to improve this, let me know. In my case I luckily only need the value after an postback.
There is no way of checking this that will fit your requirement of "secure" as stated in your comment on #WTP's answer.
I don't think the server-side can do this, so why not put a hidden control in your page that will be in the iframe? When the URL in the iframe loads, you can add some client-side code to set the hidden input to indicate you are in an iframe. The easiest check would be on the client-side in an onload method, like this:
// Set hidden input
someHiddenInput.value = self != top
It's more secure than the querystring, but it still might not be enough security for you.
My 2 cents.
Old question but why not a more simplistic approach like
var isFramed = self !== parent

Categories