I premit that I'm quite new to Anotar / Serilog, I've my WPF application that uses the Repository Pattern and I've the repo strucured as
public class CalendarRepository : DefaultRepositoryBase, ICalendarRepository
{
public Task<IList<CalendarTemplate>> GetCalendarTemplatesAsync(int? template)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CalendarTemplatesRequest
{
Template = template
};
return client.PostAsync(request);
}
public Task<IList<Currency>> GetCurrenciesAsync(int? currency)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CurrenciesRequest
{
Currency = currency
};
return client.PostAsync(request);
}
public Task<IList<CurrencyCalendar>> GetCurrencyCalendarsAsync(IEnumerable<int> currencies)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CurrencyCalendarsRequest
{
Currencies = currencies
};
return client.PostAsync(request);
}
Right now I was logging in the viewmodels as
LogTo.Information("Getting calendar currencies {SelectedCurrencies}",selectedCurrenciesId.Select(x=>x.Id));
var items = await repository.GetCurrencyCalendarsAsync(selectedCurrenciesId.Select(x => x.Id));
I was wondering if there's an Attribute that I can apply to a class in order to automatically log the Method and the parameters.
Right now my logged is configured as
var log =
new LoggerConfiguration().MinimumLevel.ControlledBy(
levelSwitch: new LoggingLevelSwitch(LogEventLevel.Debug)).WriteTo.File(#".\logs\serilog.log",outputTemplate: "{Timestamp: yyyy-MM-dd HH:mm:ss.fff} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}").CreateLogger();
Serilog.Log.Logger = log;
Thanks
You can get the method name and line number by adding {Method} and {LineNumber} to the output template respectively.
As far as I know, there is no way to automatically log the parameters; you would need to do this manually.
Related
I'm currently working on migrating a web app with the following tech:
ASP.NET MVC
AngularJs
Gulp
Azure cloud service
to :
ASP.NET Core MVC
AngularJs
Webpack
Azure App service
The migrated app correctly bundle and serve AngularJs index.html to wwwroot.
Currently, I need to add two views to the ASP.NET Core MVC app and inject the index.html to these views.
I can't figure out how to :
Inject the index.html
Make one of the views as a startup view.
to finally have an URL pattern:
localhost/View1/#/angularJs-state
or
localhost/View2/#/angularJs-state
wwwroot :
Home :
public class BaseController : Controller
{
public IActionResult Index()
{
return View("portal");
}
}
First view :
public class PortalController : Controller
{
public IActionResult Index()
{
return View();
}
}
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "portal",
pattern: "Portal",
defaults: new { controller = "Portal", action = "Index" });
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Base}/{action=Index}/{id?}");
});
The first view is correctly displayed but without the view name in
the url .
Is it possible to render the index.html from wwwroot in the cshtml
view using #html.Partial ?
According to your description, if you want to render the html page in the view, I suggest you could write a custom render method in mvc and return the index file as the file result to the mvc view.
More details, you could refer to below codes:
1.Create render extension method:
public static class HtmlHelperViewExtensions
{
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null)
{
var controller = (string)helper.ViewContext.RouteData.Values["controller"];
return RenderAction(helper, action, controller, parameters);
}
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null)
{
var area = (string)helper.ViewContext.RouteData.Values["area"];
return RenderAction(helper, action, controller, area, parameters);
}
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
{
if (action == null)
throw new ArgumentNullException(nameof(controller));
if (controller == null)
throw new ArgumentNullException(nameof(action));
var task = RenderActionAsync(helper, action, controller, area, parameters);
return task.Result;
}
private static async Task<IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
{
// fetching required services for invocation
var currentHttpContext = helper.ViewContext.HttpContext;
var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext);
var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext);
var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext);
// creating new action invocation context
var routeData = new RouteData();
var routeParams = new RouteValueDictionary(parameters ?? new { });
var routeValues = new RouteValueDictionary(new { area, controller, action });
var newHttpContext = httpContextFactory.Create(currentHttpContext.Features);
newHttpContext.Response.Body = new MemoryStream();
foreach (var router in helper.ViewContext.RouteData.Routers)
routeData.PushState(router, null, null);
routeData.PushState(null, routeValues, null);
routeData.PushState(null, routeParams, null);
var actionDescriptor = actionSelector.ActionDescriptors.Items.First(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action);
var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
// invoke action and retreive the response body
var invoker = actionInvokerFactory.CreateInvoker(actionContext);
string content = null;
await invoker.InvokeAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
content = task.Exception.Message;
}
else if (task.IsCompleted)
{
newHttpContext.Response.Body.Position = 0;
using (var reader = new StreamReader(newHttpContext.Response.Body))
content = reader.ReadToEnd();
}
});
return new HtmlString(content);
}
private static TService GetServiceOrFail<TService>(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
var service = httpContext.RequestServices.GetService(typeof(TService));
if (service == null)
throw new InvalidOperationException($"Could not locate service: {nameof(TService)}");
return (TService)service;
}
}
2.Add controller method as below:
public IActionResult IndexFile()
{
return File("index.html", "text/html");
}
3.Add below codes into view:
#Html.RenderAction("IndexFile", "Yourcontrollername")
I am creating reportviewer using Syncfusion in angular JS in Asp.net MVC
I have downloaded the community version of syncfusion
My APIController
public class Pay_rep_ReportViewerApiController : ApiController, IReportController
{
public object PostReportAction(Dictionary<string, object> jsonResult)
{
try
{
var output = ReportHelper.ProcessReport(jsonResult, this);
}
catch (Exception exxxx)
{
}
return ReportHelper.ProcessReport(jsonResult, this);
}
//Get action for getting resources from the report
[System.Web.Http.ActionName("GetResource")]
[AcceptVerbs("GET")]
public object GetResource(string key, string resourcetype, bool isPrint)
{
return ReportHelper.GetResource(key, resourcetype, isPrint);
}
//Method will be called when initialize the report options before start processing the report
public void OnInitReportOptions(ReportViewerOptions reportOption)
{
if (reportOption.ReportModel.ReportPath.Contains("RSSMRP01.rdlc"))
{
reportOption.ReportModel.ReportPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/RSSMRP01.rdlc");
}
if (reportOption.ReportModel.ReportPath.Contains("~/Views/PayModule/Pay_rep_employee.rdlc"))
{
reportOption.ReportModel.ReportPath = System.Web.HttpContext.Current.Server.MapPath(reportOption.ReportModel.ReportPath);
}
}
//Method will be called when reported is loaded
public void OnReportLoaded(ReportViewerOptions reportOption)
{
}
}
in JSController
$scope.reportServiceUrl = '/api/Pay_rep_ReportViewerApi';
$scope.remoteMode = ej.ReportViewer.ProcessingMode.Local;
$scope.rdlReportPath = '~/Views/PayModule/Pay_rep_employee.rdlc';
In my view
<div id="container" ej-reportviewer e-reportserviceurl="reportServiceUrl"
e-processingmode="remoteMode" e-isresponsive="true"
e-reportpath="rdlReportPath" style="width:100%;height:680px;"
e-datasources="dataSource">
</div>
I get json array in ApiController when I keep breakpoint
{{ inProgress = completed,
isReportLoad = True,
paramInfo = NoParams,
reportViewerToken = 930af59b-fd2d-473c-b453-e8df4343ecc7,
reportViewerID = 930af59b-fd2d-473c-b453-e8df4343ecc7,
dataSources = , dataSets = , reportParameters = , isRDLC = False,
errorInfo = , serviceType = Default }}
but on the screen with reportviewer I get "The given key was not present in the dictionary.", but the server demo works fine .
References added
Is it feasible to solve it using community version? Thanks in advance
I have WORD DOCX file in binary format in my SQL database.
I'm using c# WEB API controller to connect to database from get byte array and send it to my front end as string datatype.
Then trying to download it on a button click in my Angular 5 application.
Please find the code below,
WEB API Controller:
public Model testFunction()
{
byte[] inputWORDBytes = (byte[])ds.Tables[0].Rows[0][0];
Model model = new Model();
model.WORDFile = inputWORDBytes;
return model;
}
C# Model:
public class Model
{
public byte[] WORDFile { get; set; }
}
Angular Model:
export interface Model {
WORDFile : string;
}
Angular Component:
//Inside service method call
let binWord = atob(model.WORDFile);
let bytesWord = [];
for (let i = 0; i < binWord.length; i++) {
bytesWord.push(binWord.charCodeAt(i));
}
let documentWORD: Uint32Array = new Uint32Array(bytesWord);
var blob = new Blob([documentWORD], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
var url = window.URL.createObjectURL(blob);
window.open(url);
It downloads a word file but it is corrupted.
I am trying to save a value in the "UserController" but I cannot seem tog et it to save to the database.
I can get the database value as stored in the UserController to change so that when the value is submitted and the view is refreshed it looks as though it was stored. (ie. changing from test to tested) However, as soon as I refresh the page again it returns to the previous value and the database shows no change throughout this.
UserController:
var g = httpPost.VanityUrl;
DB.ppUser_editUser(g);
ppUser_editUser in ppUser:
public ppUser ppUser_editUser(string personVanity)
{
ppUser user = SessionUser.LoggedInUser.Person;
user.VanityUrl = personVanity;
BaseDB.SubmitChanges();
return user;
}
EditProfile View:
<div>
#Html.LabelFor(m => m.VanityUrl, "Edit your Custom Url:")
#Html.TextBoxFor(m => m.VanityUrl, new { maxlength = 15 })
</div>
BaseDB:
public partial class StudioKit_MVC3Repository : IDisposable
{
private StudioKit_MVC3ModelsDataContext _BaseDB;
public StudioKit_MVC3ModelsDataContext BaseDB
{
get
{
if (_BaseDB == null)
{
if (StudioKit_MVC3Config.EnvironmentDetail.Name == "Production")
{
_BaseDB = new StudioKit_MVC3ModelsDataContext(StudioKit_MVC3Config.EnvironmentDetail.ConnectionString);
}
else
{
var sqlConnection = new SqlConnection(StudioKit_MVC3Config.EnvironmentDetail.ConnectionString);
var conn = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
_BaseDB = new StudioKit_MVC3ModelsDataContext(conn);
}
}
return _BaseDB;
}
}
}
Edit:
I figured out the problem. I was saving the value to the session user instance and not the actual database. I got rid of the method and in the controller I simply put:
ppUser check = DB.ppUser_GetUserByPersonID(model.cskPersonID);
check.VanityUrl = httpPost.VanityUrl;
DB.Save();
To grab some content from a WCF Data Service into my View Model is straight forward:
public const string RequestsPropertyName = "Requests";
private DataServiceCollection<Request> _requests = null;
public DataServiceCollection<Request> Requests
{
get { return _requests; }
set
{
if (_requests == value) { return; }
var oldValue = _requests;
_requests = value;
RaisePropertyChanged(RequestsPropertyName, oldValue, value, true);
}
}
and then
Requests.LoadAsync(query);
But what if I have a property which is not a collection?
public const string RequestDetailsPropertyName = "RequestDetails";
private Request _requestDetails = null;
public Request RequestDetails
{
get { return _requestDetails; }
and so on.
Where do I get the 'LoadAsync(query)' method from?
Thank you,
Ueli
This is a pretty simple thing to do. You just need to use the DomainContext in your application. This is where you create your query from, then apply the result to your property.
Here is an example of what this might look like in your code:
void LoadRequest(int requstID)
{
var query = workContext.GetRequestByIDQuery(requestID);
workContext.Load(query, lo =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
if (lo.HasError)
throw lo.Error;
else
RequestDetails = lo.Entities.Single();
});
}, null);
}
In this example, the workContext object is the DomainContext. The query is an specific version on the server - you can also just contruct the query client side with:
.Where(r => r.RequestID == requestID)
After the async call, it thows any errors that occurred from the async call, and then returns the only entity returned. If you get more than 1 entity, you might use .First() instead.
If this is not enough to get you going, let me know and I can explain further.