How to use XDocument.Load to load cached pages from IIS sever - wpf

We have a WPF application which is requesting RSS feeds through url from our MVC website using XDocument.Load() function. Although in the MVC web application we are caching the RSS page for 15 minutes, the wpf application is still requesting a new rss page every time ignoring the cache in the server. How do we use the cached pages in our WPF application?
Here is the code:
Path.Combine((Directory.GetParent(App.DisplayFilePath)).Name, "RSS.xml");
XDocument doc;
doc = XDocument.Load(this.FeedUri.AbsoluteUri);
doc.Save(cacheXmlFile);
doc = XDocument.Load(cacheXmlFile);
var feedItems = from feed in doc.Descendants("item");
Here is the code in the Server side mvc application:
[OutputCache(Duration = 900, VaryByParam = "*")]
public RssActionResult GetBranches(int gid = -1, string gname = "", int t = -1,
int tgap = 0)
{
var feedItems = new List<feedItem>();
var branches = db.usp_GetBranch(gid, gname, t, tgap).ToList();
feed.Items = feedItems;
return new RssActionResult() { Feed = feed };
}
The WPF application is requesting this action through url in the server side. Is the OutputCache attribute OK?

Related

Setting Scheme programmatically of website

I have a multisite application with around 40+ Https sites. The scheme column for all the sites is empty.
I tried creating a schedule job that will update Scheme to HTTPS looping in all the sites using SiteDefinitionRepository. The problem is Scheme property is read only & so I cannot set the same.
Is there a way I can set Scheme to HTTPS rather than doing it manually for the 40+sites?
The SiteDefinition and HostDefinition implementations are IReadOnly.
Create a writable clone and set UseSecureConnection to true in the host definition
// ISiteDefinitionRepository siteDefinitionRepository
var sites = _siteDefinitionRepository.List();
foreach (var site in sites)
{
var writableSite = site.CreateWritableClone();
if (site.SiteUrl.Scheme == "http")
{
writableSite.SiteUrl = new Uri(site.SiteUrl.ToString().Replace("http", "https"));
}
var hosts = writableSite.Hosts.Where(x => !x.Name.Equals(HostDefinition.WildcardHostName));
foreach (var writableHost in hosts)
{
writableHost.UseSecureConnection = true;
}
_siteDefinitionRepository.Save(writableSite);
}
The code will turn this
in to this

How do i manage the SQL Server connections in asp.net core MVC mode?

I am working on a APP's server program which using asp.net core MVC mode. And in the XXXXcontrller i never use code like "Connection.open()" and "Connection.close()",a HTTP GET action is like this.
public async Task<IActionResult> register(string phoneNum, string password, string userType)
{
//从数据库里找到m.Id和 id相同的车,赋给dbCars
var dbCars = await _context.dbUsers.SingleOrDefaultAsync(m => m.UserName == phoneNum);
// var dbCars= _context.dbCars.Where(s => s.Id == id).FirstOrDefault<dbCars>();
if (dbCars == null)//如果为空,则注册
{
//注册新用户
dbCars = new dbUsers();
dbCars.UserName = phoneNum;
dbCars.Password = password;
dbCars.UserType = userType;
dbCars.IsVerified = true;
_context.Add(dbCars);
await _context.SaveChangesAsync();
//注册完成之后,把ID、用户类型和是否认证返回回去
List<string> userInfo = new List<string>();
userInfo.Add(dbCars.Id.ToString().Trim());
userInfo.Add(dbCars.UserType.ToString().Trim());
userInfo.Add(dbCars.IsVerified.ToString());
string json = JsonConvert.SerializeObject(userInfo);
return Ok(json);
}
else //如果不为空就代表注册过了
{
return Ok("0"); //返回1代表注册过了
}
}
I wondered how should i maintain the SQL Connections when many users access this service?? Should I close these connections manually? Or it can be done automatically by some magic?? If many users access this service, do my program breaked down??
I am confused, who can give me an answer??
if you are using Entity Framework or ORM you should see and set the connection string on the web.config or if it's on a separate layer you can see the settings on the app.config. If you run the application it will use the startup project of your application connectionstring app.config(windows application) or web.config (web application)

How to list subscriptions with Microsoft.Azure.ResourceManager?

Context
My core goal is to write an Azure WebApps deployment tool in C#. The process will be roughly
User logs in
User selects subscription
User selects or creates resource group
User selects or creates storage for the web app
User selects or creates web service plan
User selects or creates web app
Tool uploads the web app using Kudu to POST a zip
Since the last step can't be done in the portal, my idea was to do everything in a GUI tool.
I started out using Kudu's ARMClient.Authentication and Microsoft.Azure.ResourceManager 1.0.0-preview. However, when it comes to creating a storage account I get a permissions error (The subscription is not registered to use namespace Microsoft.Storage), so my plan B was to do the authentication myself following Brady Gaster's blog post.
The problem
I've set up an application as documented, and using its clientId and tenantId I'm able to log in and list tenants. But I can't list any subscriptions. (NB I've partly elided the clientId and tenantId in case there are security risks with giving them in full).
string clientId = "f62903b9-ELIDED";
string tenantId = "47b6e6c3-ELIDED";
const string redirectUri = "urn:ietf:wg:oauth:2.0:oob";
const string baseAuthUri = "https://login.microsoftonline.com/";
const string resource = "https://management.core.windows.net/";
var ctx = new AuthenticationContext(baseAuthUri + tenantId);
var authResult = ctx.AcquireToken(resource, clientId, new Uri(redirectUri), PromptBehavior.Auto);
var token = new TokenCredentials(authResult.AccessToken);
var subClient = new SubscriptionClient(token);
var tenants = await subClient.Tenants.ListAsync();
foreach (var tenant in tenants) Console.WriteLine(tenant.TenantId);
var subs = await subClient.Subscriptions.ListAsync();
foreach (var sub in subs) Console.WriteLine(sub.DisplayName);
When I run this it prompts me to login, and lists the tenants corresponding to the subscriptions I own or co-administer. But it doesn't list a single subscription. If I change the IDs to the commonly used (I think officially for Powershell) values
clientId = "1950a258-227b-4e31-a9cf-717495945fc2";
tenantId = "common";
then it's the same.
What is the step I've missed in order to get a list of my subscriptions?
You need to iterate through the tenants, authenticate in tenant and get a subscription list for every tenant.
The following code will output the Subscriptions like Get-AzureRmSubscription powershell cmdlet does.
class Program
{
private static string m_resource = "https://management.core.windows.net/";
private static string m_clientId = "1950a258-227b-4e31-a9cf-717495945fc2"; // well-known client ID for Azure PowerShell
private static string m_redirectURI = "urn:ietf:wg:oauth:2.0:oob"; // redirect URI for Azure PowerShell
static void Main(string[] args)
{
try
{
var ctx = new AuthenticationContext("https://login.microsoftonline.com/common");
// This will show the login window
var mainAuthRes = ctx.AcquireToken(m_resource, m_clientId, new Uri(m_redirectURI), PromptBehavior.Always);
var subscriptionCredentials = new TokenCloudCredentials(mainAuthRes.AccessToken);
var cancelToken = new CancellationToken();
using (var subscriptionClient = new SubscriptionClient(subscriptionCredentials))
{
var tenants = subscriptionClient.Tenants.ListAsync(cancelToken).Result;
foreach (var tenantDescription in tenants.TenantIds)
{
var tenantCtx = new AuthenticationContext("https://login.microsoftonline.com/" + tenantDescription.TenantId);
// This will NOT show the login window
var tenantAuthRes = tenantCtx.AcquireToken(
m_resource,
m_clientId,
new Uri(m_redirectURI),
PromptBehavior.Never,
new UserIdentifier(mainAuthRes.UserInfo.DisplayableId, UserIdentifierType.RequiredDisplayableId));
var tenantTokenCreds = new TokenCloudCredentials(tenantAuthRes.AccessToken);
using (var tenantSubscriptionClient = new SubscriptionClient(tenantTokenCreds))
{
var tenantSubscriptioins = tenantSubscriptionClient.Subscriptions.ListAsync(cancelToken).Result;
foreach (var sub in tenantSubscriptioins.Subscriptions)
{
Console.WriteLine($"SubscriptionName : {sub.DisplayName}");
Console.WriteLine($"SubscriptionId : {sub.SubscriptionId}");
Console.WriteLine($"TenantId : {tenantDescription.TenantId}");
Console.WriteLine($"State : {sub.State}");
Console.WriteLine();
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
Console.WriteLine("press something");
Console.ReadLine();
}
}
}
A couple things you can look into...
1) the error you saw during creating of the storage account is likely due to the Resource Provider not being registered for use with the subscription. Any RP needs to be registered before use, some clients (Portal, PowerShell) will register the RP for you so you never notice it. See: https://msdn.microsoft.com/en-us/library/azure/dn790548.aspx - you should be able to do that from your code if the user has sufficient perms.
2) You may not be getting any subscriptions back because your endpoint (management.core.windows.net) is the endpoint for Azure Service Management not Azure Resource Manager (management.azure.com). If the subscription access is granted via AzureRM and RBAC, the old ASM apis will not see (i.e. have access to) those subscriptions.

Content migration error from Ektron to EpiServer

I am working on a content migration project , from Ektron 9 to EpiServer 8, the first task is to migrate the content of specific pages , to achieve that, I was following Ektron's API guidance Ektron Developer API
1- I am approaching this migration the right way? right now I just added Ektron Dll as a reference in my app. I tried to use their web services , but it doesn't have the data i need (content of specific pages).Ektron Web Services
here's a snippet of my code:
GetAllTemplatesRequest cc = new GetAllTemplatesRequest();
//var UserCRUD = new Ektron.Cms.Framework.User.UserManager();
var UserCRUD = new UserManager();
string Token = UserCRUD.Authenticate("admin", "password");
if (!string.IsNullOrEmpty(Token)) // Success
{
try
{
//Create the Content Object set to observe permissions
Ektron.Cms.Framework.Content.ContentManager ContentAPI
= new Ektron.Cms.Framework.Content.ContentManager(ApiAccessMode.Admin);
//Retrieve the content
Ektron.Cms.ContentData contentData;
contentData = ContentAPI.GetItem(30);
//Output the retrieved item's content
var cs = contentData.Html;
}
catch (Exception _e)
{
throw _e;
}
}
else // Fail
{
}
But I am getting this error:
This is what i ended up doing :
As there are many ways to perform the migration , I chose the approach of focusing mainly on EpiServer APIs to create new content , blocks, and assets ; and get all the content i need from Ektron using SQL statements.
Ektron Save all the content in a table named content .
The pages are organized in “Folder structure” fashion , so every page is in a “Folder”
to get the folder ID for a specific page, you can use this query :
select folder_id from content where content_id = 2147485807
with that folder id you can get all the pages listed under that specific folder; for instance you will need to get all the pages under “Articles”.
Then i used that folderID in this query:
SELECT [content_id]
,[content_title]
,[content_html]
,[date_created]
,folder_id
,[content_teaser]
,[content_text]
,[end_date]
,[content_type]
,[template_id]
, content_status
FROM content
where folder_id=(select folder_id from content where content_id = 2147485807)
order by content_title
FOR XML PATH(‘Article’), ROOT (‘Articles’)
which Creates an XML for me ready to consume in my EpiServer code.
The first thing in EPI server I did is to add a new property in the SitePageBase model to add a “LegacyContentID” that will serve as a mapping entry in case i need to access/modify the content of the new created pages. it serves as a link between the data imported from Ektron and the new data i am creating on EPI server.
[Display(
Name = “Legacy Content ID”,
Description = “Content ID from Ektron imported data , for migration purposes”,
GroupName = GroupNames.PageSettings,
Order = 37)]
[ScaffoldColumn(false)]
[Editable(false)]
public virtual string LegacyContentID { get; set; }
Then i created a method to create the article pages , the only parameter it needs is the parentID from IP server (you can create a new page in EpiServer and then under properties of that page you can the page ID).
public void CreateArticlesPages(int parentID)
{
IContentRepository contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
var parentlink = new ContentReference(parentID);
XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText(#”Articles.xml”));
string jsonText = JsonConvert.SerializeXmlNode(doc);
dynamic data = JsonConvert.DeserializeObject(jsonText);
for (int i = 0; i < data.Articles.Article.Count; i++)
{
var PageImportedObject = data.Articles.Article[i];
ArticlePage page = contentRepository.GetDefault<ArticlePage>(parentlink);
page = contentRepository.GetDefault<ArticlePage>(parentlink);
page.LegacyContentID = PageImportedObject.content_id;
page.Name = PageImportedObject.content_title;
page.PageTitle = PageImportedObject.content_title;
if (PageImportedObject.content_teaser == null)
page.Summary = “No Summary from the Ektron DB”;
else
page.Summary = PageImportedObject.content_teaser;
page.Description = PageImportedObject.content_html.root.Description;
contentRepository.Save(page, EPiServer.DataAccess.SaveAction.Save, EPiServer.Security.AccessLevel.NoAccess);
contentRepository.Save(page, EPiServer.DataAccess.SaveAction.Publish, EPiServer.Security.AccessLevel.NoAccess);
}
}
The code above creates a new page of type “ArticlePage” and add content from the XML generated earlier holding Ektron’s info.
Just coping one dll from an Ektron site into another site will not work.
The Web services idea was a better one. There are web service calls to get the content by id.
Alternatively you could write your own web service that runs inside the ektron site and uses the Ektron API to expose the data you want. Then call that service from the other site.
You will want to review the content migration starter kit. https://github.com/egandalf/ContentTransferStarterKit

CefSharp.Wpf: Open csv, mailto and pdf with Process.Start(...)

I need to handle different content types from f:///. My application renders offline websites in a WPF application. Everything is working except for links to other content files (csv, mailto and pdf).
If I register a CefCustomScheme for "mailto", then I get the ProcessRequestAsync and can run the Process.Start(...). However another blank window also popup.
If I then add a second CefCustomScheme for "file", then nothing happens. None of the ISchemeHandler ProcessRequestAsync methods are invoked.
I must be able to handle all requests, excluding *.html, in a separate handler
Essentially I just want to replicate the behavior of the MS Web-browser Control. There all I did was point to the entry page (index.htm), and everything loaded. Then if a user clicks any link, the control handled the action and started the correct process (content handler, i.e. Excel for Csv).
The code:
// Startup
var settings = new CefSettings();
settings.LogFile = #"c:\temp\ceflog.txt";
settings.LogSeverity = LogSeverity.Verbose;
settings.IgnoreCertificateErrors = true;
CefCustomScheme mailtoScheme = new CefCustomScheme();
mailtoScheme.SchemeName = "mailto";
mailtoScheme.SchemeHandlerFactory = new SchemeHandlerFactory();
CefCustomScheme filesScheme = new CefCustomScheme();
mailtoScheme.SchemeName = "file";
mailtoScheme.SchemeHandlerFactory = new SchemeHandlerFactory();
settings.RegisterScheme(mailtoScheme);
settings.RegisterScheme(filesScheme);
if (!Cef.Initialize(settings))
throw new InvalidOperationException("Failed to initialize the browser factory");
-- SchemeHandlerFactory
public class SchemeHandlerFactory : ISchemeHandlerFactory {
public ISchemeHandler Create() {
return new CustomSchemeHandler();
}
}
-- Handler
public class CustomSchemeHandler : ISchemeHandler {
private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public bool ProcessRequestAsync(IRequest request, ISchemeHandlerResponse response, OnRequestCompletedHandler requestCompletedCallback) {
_log.DebugFormat("Processing url: {0}", request.Dump());
var knownContentTypes = new[] {".csv", ".xsls", ".xlsx", ".pdf", ".txt"};
var ext=Path.GetExtension(request.Url);
if(knownContentTypes.Contains(ext)) {
_log.DebugFormat("Starting process for: {0}",request.Url);
Process.Start(request.Url);
return false;
}
return true;
}
The solution was to implement an IRequestHandler and use the OnBeforeResourceLoad event to check what content was requested. The ISchemeHandler is used for the "mailto" actions.
In my case I had to assign the request handler after the frame loaded. This allowed the web browser to render all content first.
Code sample GitHub example

Resources