How to display error message from exception without redirecting to new view in MVC 4 - asp.net-mvc-4

I would like to catch exceptions that might bubble up from a class library method to the action from which it was called and would like to display the error in the view without actually redirecting to a new view. I've overriden the OnException method in my controller and have created a partial view to display the error but when an error occurs the partial view is not being rendered where I want it to show but rather where I have a table and it will be replaced with the error message which is not what I wan, not to mention the table is in a different place in the view than where the error should display. I haven't done much exception handling with MVC so I don't know if my approach is completely wrong.
My code for the exception
protected override void OnException(ExceptionContext filterContext)
{
Exception ex = filterContext.Exception;
filterContext.ExceptionHandled = true;
var controllerName = (string)filterContext.RouteData.Values["controller"];
var actionName = (string)filterContext.RouteData.Values["action"];
var exp = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
//Assigns error message to property for message in view model
ReceivngFormViewModel viewModel = new ReceivngFormViewModel
{
ErrorMessage = exp.Exception.Message
};
filterContext.Result = new PartialViewResult()
{
//_Error is the partial view
ViewName = "_Error",
ViewData = new ViewDataDictionary(viewModel)
};
}

this code help you use ModelState.AddModelError
**Controller**
Model obj=new Model();
try{
}
cathch(exception ex){
ModelState.AddModelError("objectname", ex.tostring());
}
return obj;
**Viwe**
#Html.ValidationMessageFor(model => model.objectname)

Related

Where to call async GetDataFromServer in Xamarin.Forms?

Where would be the best place to call GetDataFromServer method?
My gut feeling and reason say it belongs in the repository, but I've no clue where to call it. I've tried to call it in the constructor, but that didn't work out too well. It had issues with it being an async method.
public class SQLiteRepository : ISQLiteRepository
{
private HttpClient _httpClient = new HttpClient();
private readonly SQLiteAsyncConnection _efContext;
public SQLiteRepository()
{
_efContext = DependencyService.Get<ISQLiteDb>().GetAsyncConnection();
_efContext.CreateTableAsync<EfPartner>();
}
public async Task<IEnumerable<EfPartner>> GetAllPartnersAsync()
{
try
{
var partners = await _efContext.Table<EfPartner>().ToListAsync();
return partners;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task GetDataFromServerAsync()
{
try
{
var partners = await GetPartnersFromServerAsync();
var companies = await GetCompaniesFromServerAsync();
await _efContext.InsertAllAsync(partners);
}
catch (Exception ex)
{
throw ex;
}
}
private async Task<IEnumerable<EfPartner>> GetPartnersFromServerAsync()
{
try
{
var jsonObject = await _httpClient.GetStringAsync(Constants.PartnersUrl);
var dotNetObject = JsonConvert.DeserializeObject<List<EfPartner>>(jsonObject);
return new List<EfPartner>(dotNetObject);
}
catch (Exception ex)
{
throw ex;
}
}
private async Task<IEnumerable<EfCompany>> GetCompaniesFromServerAsync()
{
try
{
var jsonObject = await _httpClient.GetStringAsync(Constants.CompaniesUrl);
var dotNetObject = JsonConvert.DeserializeObject<List<EfCompany>>(jsonObject);
return new List<EfCompany>(dotNetObject);
}
catch (Exception ex)
{
throw ex;
}
}
}
I called the GetDataFromServerAsync from PartnersListPage.xaml.cs -> which feels wrong.
I'd appreciate any help.
Thank you.
============================ UPDATE ============================
The app I'm working on creates the pages in a MasterDetailPage like so:
private void MenuListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
return;
var menuItem = e.SelectedItem as EfMenuItem;
if (menuItem == null)
return;
var page = (Page)Activator.CreateInstance(menuItem.TargetPage);
page.Title = menuItem.Title;
Detail = new NavigationPage(page);
IsPresented = false;
MdpMasterPage.MenuListView.SelectedItem = null;
}
And here is the PartnersListPage.xaml.cs, from where is GetDataFromServer called at the moment:
public partial class PartnersListPage : ContentPage
{
private readonly SQLiteRepository _repo;
public PartnersListPage()
{
InitializeComponent();
_repo = new SQLiteRepository();
}
protected override async void OnAppearing()
{
await _repo.GetDataFromServerAsync();
var partners = await _repo.GetAllPartnersAsync();
InitializeGrid(partners);
base.OnAppearing();
}
This is an important topic related to MVVM, what you are doing is "correct" but it may have issues later on once your application grow bigger, let's imaging this scenario:
The user is a desperate one and he/she wants to Navigate on your app real fast, he/she open this specific page 5 or 10 times, what will happen then?
Your OnAppearing() method will be called every time the user lands on this page and a new thread will be created for instance your application will start to behave poorly on the performance part. (Specially on Android).
So my suggestion will be to use an MVVM framework to handle those cases based on the pattern, here is a small tutorial using Prism:
https://xamgirl.com/prism-in-xamarin-forms-step-by-step-part-1/
And in regards of your question, your UI ListView specifically your ItemSource (If you are using a ListView) property should be binded to your GetAllPartnersAsync() return type.
If that is not the case and based on the context I suppose InitializeGrid(partners); is creating cells for a Grid in your XAML class so I suppose you can debug step by step if the UI is being created correctly. A Grid does not have an ItemSource property
If you want to have a Grid with an ItemSource property I suggest you sue this ones:
https://github.com/Manne990/XamTest
https://github.com/daniel-luberda/DLToolkit.Forms.Controls/tree/master/FlowListView

Value cannot be null. Parameter name: view

I was trying to render a dynamic view into string.I got the idea from here and it is working well locally but on hosting I am getting the following error.My attempt is to convert the string to bytes for sending email
Value cannot be null. Parameter name: view
Controller
public ActionResult Index(int RegId)
{
try
{
var _mdlReceiptPdf = new ReceiptPdfVM
{
...
...
};
string result = RazorViewToString.RenderRazorViewToString(this, Server.MapPath("~/Views/Shared/_Receipts.cshtml"), _mdlReceiptPdf);
StringReader _sr = new StringReader(result);
return Json(result, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(ex.Message, JsonRequestBehavior.AllowGet);
}
}
Util.cs
public static class RazorViewToString
{
public static string RenderRazorViewToString(this Controller controller, string viewName, object model)
{
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
}
I had this problem. In my case, it turned out that the partial view wasn't being uploaded to the hosted website because in the File Properties for the partial view, the BuildAction was set to None instead of Content
Yeah looks like this error is saying view can't be found.
In my case I had a typo for the view name in the controller.
_QuickView.cshtml instead of QuickView.cshtml

Web API Controller Method -- Request is null

When calling the method shown below, Request is always null. I have some simple methods returning JSON data from controllers in an MVC4 app with controllers using ApiController as a base class. The code for my directory function is as follows:
public HttpResponseMessage GetDirectory() {
try {
var dir = r.GetDirectory();
if (dir == null) {
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError));
}
var response = Request.CreateResponse(HttpStatusCode.OK, dir, "application/json");
response.Headers.Location = new Uri(Request.RequestUri, "directory");
return response;
} catch (Exception ex) {
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
}
}
When this method is called, 'dir' is loaded properly from r.GetDirectory(). But Request is null. So naturally Request.CreateResponse() fails, and so on. I am looking for reasons why Request would be null, or for a rewrite that allows the return to remain an HttpResponseMessage.
This is being called (in my unit test project) with:
var ctrl = new DirectoryController();
var httpDir = ctrl.GetDirectory();
Thanks for your help.
Olav Nybø left me the hint that led to the answer. In response to ASP.NET WebApi unit testing with Request.CreateResponse, jonnii suggested the following code:
controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
This led to a nice way to test controllers:
var controller = new RecordsController();
controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
var json = controller.GetAllRecords(id);
var records = JsonConvert.DeserializeObject<DynamicRecordSet>(json.Content.ReadAsStringAsync().Result);

How to handle error in Primefaces lazy load?

I have problem to let user know about exceptions occurred in PrimeFaces LazyDataModel#load method.
I am loading there data from database and when an exception is raised, I have no idea how to inform the user about it.
I tried to add FacesMessage to FacesContext, but message is not shown on the Growl component, even if Growl is set to autoUpdate="true".
Using PrimeFaces 3.3.
It doesn't work because load() method is invoked during Render Response phase (you can check this by printing FacesContext.getCurrentInstance().getCurrentPhaseId()), when all messages have already been processed.
The only workaround that worked for me is to load the data within the "page" event listener of the DataTable.
html:
<p:dataTable value="#{controller.model}" binding="#{controller.table}">
<p:ajax event="page" listener="#{controller.onPagination}" />
</p:dataTable>
Controller:
private List<DTO> listDTO;
private int rowCount;
private DataTable table;
private LazyDataModel<DTO> model = new LazyDataModel<DTO>() {
#Override
public List<DTO> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, String> filters) {
setRowCount(rowCount);
return listDTO;
}
};
public void onPagination(PageEvent event) {
FacesContext ctx = FacesContext.getCurrentInstance();
Map<String, String> params = ctx.getExternalContext()
.getRequestParameterMap();
// You cannot use DataTable.getRows() and DataTable.getFirst() here,
// it seems that these fields are set during Render Response phase
// and not during Update Model phase as one can expect.
String clientId = table.getClientId();
int first = Integer.parseInt(params.get(clientId + "_first"));
int pageSize = Integer.parseInt(params.get(clientId + "_rows"));
try {
listDTO = DAO.query(first, pageSize);
rowCount = DAO.getRowCount();
} catch (SQLException e) {
ctx.addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"SQL error",
"SQL error"));
}
}
Hope this helps.

Mvc4 WepApi Empty Response when non 200

When an Action is called and throws a specific exception, I use an ExceptionFilterAttribute that translate the error into a different response as HttpStatusCode.BadRequest. This has been working locally, but we pushed it to a server and now when I get the BadRequest I do not get any information in the reponse. What am I missing?
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
MyException ex = actionExecutedContext.Exception as MyException;
if (ex == null)
{
base.OnException(actionExecutedContext);
return;
}
IEnumerable<InfoItem> items = ex.Items.Select(i => new InfoItem
{
Property = i.PropertyName,
Message = i.ToString()
});
actionExecutedContext.Result = new HttpResponseMessage<IEnumerable<InfoItem>>(items, HttpStatusCode.BadRequest);
}
Edit: When I hit the service locally the body is included. It seems the problem is when hitting the service from a remote machine.
Try this:
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always