Working on Project which is mixture of ASP.Net Web Forms & MVC.
Scenario : In an Web Form application , part of an page is rendering using MVC Partial View as shown below image.
In Web Form aspx page , have defined an Div with ID = MVCPartialView1 and using Jquery Ajax successfully can bind the returned Partial View to Web Form.
$.ajax(
{
success: function (msg) { $("#MVCPartialView1").html(msg); }
});
For Handling Error Scenario made use of the following code.
[AttributeUsage(AttributeTargets.Class)]
public sealed class ErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
// Execute the normal exception handling routine
base.OnException(filterContext);
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new ViewResult
{
ViewName = "CustomError.aspx"
};
}
}
}
Base Controller :
[ErrorAttribute]
public class BaseController : Controller
Actual Problem is when an any exception occurred inside MVC Partial View ( Controller ) , CustomError is displayed only inside DIV MVCPartialView1 but it would make sense to show CustomError as full Contain of WebForm.aspx
But Expected CustomError Message is :
You can make it work only with js in your scenario.
Some thing like this:
$.ajax(
{
success: function (msg)
{
if(msg.indexOf("Error") > -1) //You should check if Error page returned
{
window.location.href = "CustomError.aspx"; //Here if redirect to error of full page
}
else
{
$("#MVCPartialView1").html(msg);
}
}
});
Related
**I have an index.cshtml inside a path like TeacherArea/Home/Index where I have this following actionlink: **
#Html.ActionLink("Edit", "EditTeachers", "Home", new { Area = "TeacherArea", id = item.id }, new { })
The purpose is to edit simple table row data.
My Home Controller looks like this:
namespace DemoProject2MVC.Areas.TeacherArea.Controllers
[RouteArea("TeacherArea")]
[RoutePrefix("TeacherArea/Home")]
public class HomeController : Controller
{
return view();
}
[Route("EditTeachers")]
public ActionResult Edit(int id)
{
MyDBContext stn = new MyDBContext();
Teacher tchr = stn.Teacher.Where(a => a.id == id).FirstOrDefault();
return View(tchr);
}
** I also have set namespace in "TeacherAreaAreaRegistration" of the controller class present inside the area like the following:**
public class TeacherAreaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "TeacherArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"TeacherArea_default",
"TeacherArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new[] { "DemoProject2MVC.Areas.TeacherArea.Controllers" }
);
}
}
I also have my global.asax like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
DataAccessLayer.StartUpClass.Start();
}
My issue is:
The index action method is calling fine within this mentioned area. But the actionlink to call Edit Action method is throwing 404.
https://localhost:44336/TeacherArea/Home/EditTeachers/7
I may be a bit rusty on MVC, but I think that if you want to mix attribute-based area declarations/routing with area/route registration in startup you need to make sure you are registering stuff in the proper order.
Another thing I noticed was that you're never calling RouteTable.Routes.MapMvcAttributeRoutes(); in your startup -- is that intentional?
If you are using both Areas with route attributes, and areas with convention based routes (set by an AreaRegistration class), then you need to make sure that area registration happen after MVC attribute routes are configured, however before the default convention-based route is set. The reason is that route registration should be ordered from the most specific (attributes) through more general (area registration) to the mist generic (the default route) to avoid generic routes from “hiding” more specific routes by matching incoming requests too early in the pipeline.
MSDN
Maybe you can try Ajax approach..
return $.ajax({
type: 'POST',
url: '<URL you want>',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ Id: id}),
success: function (data) {
...
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
...
}
});
And your controller
[HttpPost]
public JsonResult EditTeachers(int Id)
{
MyDBContext stn = new MyDBContext();
Teacher tchr = stn.Teacher.Where(a => a.id == id).FirstOrDefault();
return Json(tchr, JsonRequestBehavior.AllowGet);
}
It might be easier to debug because you can see the where the Ajax request is going from this by inspecting the network.
Hope it helps
I have the following customized validator :
public class CAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//if ajax request set status code and end responcse
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.Write(/*some data*/);
filterContext.HttpContext.Response.End();
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
and the following Action
[HttpPost]
[CAuthorize]
public ActionResult Comment(Comment comment_obj)
{
if (ModelState.IsValid)
{
this.tblSomthing.comments.Add(comment_obj);
this.db.SaveChanges();
}
return /*some view*/
}
why when the validator fails the action is executed and the DB record is saved but the response is correct (the one that is set in the validator)
I just want to stop the execution of the action if the validator fails.
You know that an action needs to return a view in order the user sees some form of output? Using Response.Write or Response.End in a controller does nothing.
Anyway what you have there is an attribute, not a validator.
If it were a validator it'd be inside the model used in the view, applied to a property.
I'm using autofac with asp.net. In Global.asax I register all my web pages:
AssertNotBuilt();
// Register Web Pages
m_builder.RegisterAssemblyTypes(typeof(AboutPage).Assembly)
.Where(t => t.GetInterfaces().Contains(typeof(IHttpHandler)))
.AsSelf().InstancePerLifetimeScope();
m_container = m_builder.Build();
m_wasBuilt = true;
Then I use a custom httpHandler to get the current web page:
public class ContextInitializerHttpHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
//Get the name of the page requested
string aspxPage = context.Request.Url.AbsolutePath;
if (aspxPage.Contains(".aspx"))
{
// Get compiled type by path
Type webPageBaseType = BuildManager.GetCompiledType(aspxPage).BaseType;
// Resolve the current page
Page page = (Page)scope.Resolve(webPageBaseType);
//process request
page.ProcessRequest(context);
}
}
public bool IsReusable
{
get { return true; }
}
}
All works ok, but then when it enters the web page_load, I see that all the asp controls that exist on the page are null. Why are they null and how do I initialize them?
I figured it out. The pages that I registered aren't compiled like the pages that I can take from the context in my http handler:
string aspxPage = context.Request.Url.AbsolutePath;
Type webPageBaseType = BuildManager.GetCompiledType(aspxPage);
and these are the pages that I need that do hold all the controls. The problem is, I can't register them at my http handler because they are dynamic and look in a form of somewebpage_aspx and the assembly is App_Web_somewebpage.aspx.cdcab7d2.r3x-vs2n, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
So the solution (or hack..) was not to register the web pages, and instead resolve the page controls from the scope:
ILifetimeScope scope = IocInitializer.Instance.InitializeCallLifetimeScope();
Type webPageType = BuildManager.GetCompiledType(aspxPage);
Page page = (Page)Activator.CreateInstance(webPageType);
foreach (var webPageProperty in webPageType.GetProperties(BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public))
{
if (scope.IsRegistered(webPageProperty.PropertyType))
{
var service = scope.Resolve(webPageProperty.PropertyType);
webPageProperty.SetValue(page, service, null);
}
}
I am in a legacy asp.net application and I need to call a method within a class via jQuery ajax post.
So far I have a class called NewClass with a single method;
[WebMethod]
public string jQuery_GetCategoryDescription(string CategoryName)
{
return "Slappy";
}
I then have the following jQuery;
$.post('/NewClass/jQuery_GetCategoryDescription', { CategoryName: "trippy" }, function (newHTML) {
alert(newHTML);
});
I've tried putting in the whole namespace in.
However I can't seem to call the method within the class.
EDIT
I am getting a 405 error
If the
[WebMethod]
public string jQuery_GetCategoryDescription(string CategoryName)
{
return "Slappy";
}
Is in side Index.aspx
You can call it by /Index.aspx/jQuery_GetCategoryDescription
I have AdminError.aspx and Error.aspx pages and I want to display AdminError.aspx when there is an exception. I need both files.
Why this doesn't work?
<customErrors mode="On" redirectMode="ResponseRedirect" defaultRedirect="AdminError.aspx" />
Instead Error.aspx is always displayed.
What can I do?
Asp.net mvc provide [HandleError] attribute to handle this kind of requirement, you can specify different error page (view) you want to redirect to based on specific error type. It's very flexible and recommended to do that way.
For example
[HandleError(ExceptionType = typeof(NullReferenceException),
View = "NullError")]
[HandleError(ExceptionType = typeof(SecurityException),
View = "SecurityError")]
public class HomeController : Controller
{
public ActionResult Index()
{
throw new NullReferenceException();
}
public ActionResult About()
{
return View();
}
}
Check out this similar question to find out more information.
Thanks,
I think I found a solution.
I'm using HandleErrorWithELMAHAttribute (How to get ELMAH to work with ASP.NET MVC [HandleError] attribute?)
and in OnException method I've set my view:
public override void OnException(ExceptionContext context)
{
View = "AdminError"; // this is my view
base.OnException(context);
var e = context.Exception;
if (!context.ExceptionHandled // if unhandled, will be logged anyhow
|| RaiseErrorSignal(e) // prefer signaling, if possible
|| IsFiltered(context)) // filtered?
return;
LogException(e);
}
I've noticed that it works with and without redirectMode and defaultRedirect attributes from customErrors tag.